Skip to content

Class static members type constraintΒ #57422

Closed as not planned
Closed as not planned
@Zamralik

Description

@Zamralik

πŸ” Search Terms

class static members type
class static type
class static interface
class static implements
class static members constraint

βœ… Viability Checklist

⭐ Suggestion

Add the ability to type classes static members using the satisfies keyword.

Reuse satisfies because it must not alter the effective type of the class, only constrained it.

πŸ“ƒ Motivating Example

TypeScript let you type constrained instanciated objects.

type Chatty = {
    speak: () => string;
};

class Dog implements Chatty
{
    private name: string;

    public constructor(name: string)
    {
        this.name = name;
    }

    public speak(): string
    {
        return `${this.name} says "Woof!".`;
    }
}

Let's imagine that we want to abstract object serialization, it would be natural to require it to have both a serialize method, and a deserialize static method.

Originally we would have only been able to define serialize as it was impossible to type the static members of a class. Until now!

type Serializable = {
    serialize(): string;
};

type ReversiblySerializable<T> = {
    new(...args: any[]): T & Serializable;
    deserialize(stringified: string): T;
};

class Point satisfies ReversiblySerializable<Point>
{
    public x: number;
    public y: number;

    public constructor(x: number, y: number)
    {
        this.x = x;
        this.y = y;
    }

    public serialize(): string
    {
        return `${this.x},${this.y}`;
    }

    public static deserialize(stringified: string): Point
    {
        const [x, y] = stringified.split(",");

        return new Point(+x, +y);
    }
}

πŸ’» Use Cases

  1. What do you want to use this for?
    Enforce generalized class static members to be properly normalized.

  2. What shortcomings exist with current approaches?
    You cannot type static members cleanly.

  3. What workarounds are you using in the meantime?
    I have a utility function that does nothing for the sole purpose of generating errors in TS in the file where the class is declared rather than where the constructor is used.
    But it pollute the resulting JS code with pointless code at runtime.

// @ts-expect-error: unused parameter because it's not supposed to do anything at runtime.
export function staticImplements<T>(constructor: T): void {}

Example of use:

export class Point { /* ... */ }

staticImplements<ReversiblySerializable<Point>>(Point);

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions