Typescript: рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╣реБрд░реВрдкреА "рдпрд╣"

рдХреЛ рдирд┐рд░реНрдорд┐рдд 1 рджрд┐рд╕ре░ 2015  ┬╖  150рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: microsoft/TypeScript

рдПрдХ рдХрд╛рдлреА рдмреБрдирд┐рдпрд╛рджреА, рд▓реЗрдХрд┐рди рдмрд╣реБрд░реВрдкреА, рд╕рдХреНрд░рд┐рдп рд░рд┐рдХреЙрд░реНрдб рд╢реИрд▓реА рдореЙрдбрд▓ рдкреНрд░рдгрд╛рд▓реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рд╣рдо рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд╕рд╛рде рдореБрджреНрджреЛрдВ рдореЗрдВ рднрд╛рдЧ рд▓реЗрддреЗ рд╣реИрдВ, рдЬрдм рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдпрд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ/рдЬреЗрдиреЗрд░рд┐рдХ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ this рд╕рдореНрдорд╛рди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрд╣рд▓реЗ рдпрд╣рд╛рдВ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рд╣реИ, #5493, рдФрд░ #5492 рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рднреА рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддрд╛ рд╣реИред

рдФрд░ рдпрд╣рд╛рдБ рдПрдХ SO рдкреЛрд╕реНрдЯ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдмрдирд╛рдпрд╛ рд╣реИ:
http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript-unsolved

рдореИрдВрдиреЗ рдЖрдЧреЗ рдХреА рдЪрд░реНрдЪрд╛ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдЯрд┐рдХрдЯ рдореЗрдВ #5493 рд╕реЗ рдЕрдкрдирд╛ рдЙрджрд╛рд╣рд░рдг рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред рдореИрдВ рдПрдХ рдЦреБрд▓реА рдЯрд┐рдХрдЯ рдЪрд╛рд╣рддрд╛ рдерд╛ рдЬреЛ рдРрд╕реА рдЪреАрдЬ рдФрд░ рдЪрд░реНрдЪрд╛ рдХреЗ рд▓рд┐рдП рдЗрдЪреНрдЫрд╛ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реЛ рд▓реЗрдХрд┐рди рдЕрдиреНрдп рджреЛ рдмрдВрдж рд╣реИрдВред

рдпрд╣рд╛рдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдПрдХ рдореЙрдбрд▓ Factory рдХреА рд░реВрдкрд░реЗрдЦрд╛ рддреИрдпрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдореЙрдбрд▓ рддреИрдпрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк BaseModel Factory рд╡рд╛рдкрд╕ рдЖрддрд╛ рд╣реИ рддреЛ рдЖрдкрдХреЛ рдЗрд╕реЗ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдп рдореЗрдВ this рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

// Typically in a library
export interface InstanceConstructor<T extends BaseModel> {
    new(fac: Factory<T>): T;
}

export class Factory<T extends BaseModel> {
    constructor(private cls: InstanceConstructor<T>) {}

    get() {
        return new this.cls(this);
    }
}

export class BaseModel {
    // NOTE: Does not work....
    constructor(private fac: Factory<this>) {}

    refresh() {
        // get returns a new instance, but it should be of
        // type Model, not BaseModel.
        return this.fac.get();
    }
}

// Application Code
export class Model extends BaseModel {
    do() {
        return true;
    }
}

// Kinda sucks that Factory cannot infer the "Model" type
let f = new Factory<Model>(Model);
let a = f.get();

// b is inferred as any here.
let b = a.refresh();

рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдореБрджреНрджрд╛ рдореВрд░реНрдЦрддрд╛рдкреВрд░реНрдг рд╣реЛ рдФрд░ рдЗрд╕рдХрд╛ рдПрдХ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рд╣реЛред рдореИрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХрд╛ рд╕реНрд╡рд╛рдЧрдд рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдкреИрдЯрд░реНрди рдХреЛ рдХреИрд╕реЗ рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

In Discussion Suggestion

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдХреНрдпрд╛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдХрд╛рд░рдг рд╣реИ?

рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ рдпрд╣ рд╕реНрдЯреИрдЯрд┐рдХреНрд╕ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдореВрд▓ рд░реВрдк рд╕реЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдбреАрдУрдП рдмрдирд╛рддрд╛ рд╣реИ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВред рдореБрдЭреЗ рдЖрдЬ рддрдХ рдХрднреА рднреА рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдкрд░ рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдлрд┐рд░ рднреА рдореБрдЭреЗ рд╕реНрдЯреЗрдЯрд┐рдХреНрд╕ рдкрд░ рд╣рд░ рдХреБрдЫ рд╣рдлреНрддреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╢реБрд░реБрдЖрддреА рджрд┐рдиреЛрдВ рдореЗрдВ рд╕реНрдЯреЗрдЯрд┐рдХреНрд╕ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдЕрдВрддрд┐рдо рд░реВрдк рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЬрдм рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреА рдШреЛрд╖рдгрд╛ рдХреА рдЧрдИ рддреЛ рдореБрдЭреЗ рдмрд╣реБрдд рдЦреБрд╢реА рд╣реБрдИ, рдлрд┐рд░ рдмрд╛рдж рдореЗрдВ рдЬрдм рдпрд╣ рдорд╣рд╕реВрд╕ рд╣реБрдЖ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рддреЛ рдореБрдЭреЗ рдмрд╣реБрдд рдЦреБрд╢реА рд╣реБрдИред

рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рдмрд╣реБрдд рд╣реА рдмреБрдирд┐рдпрд╛рджреА рдФрд░ рдмреЗрд╣рдж рд╕рд╛рдорд╛рдиреНрдп рд╣реИред рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдлрд╝реИрдХреНрдЯрд░реА рд╡рд┐рдзрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:

class Animal
{
    static create(): this
    {
        return new this();
    }
}

class Bunny extends Animal
{
    hop()
    {
    }
}

Bunny.create().hop() // Type error!! Come on!!

рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдореИрдВ рдпрд╛ рддреЛ рдмрджрд╕реВрд░рдд рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗ рд░рд╣рд╛ рд╣реВрдВ рдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рдореЗрдВ static create() рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рди рд╣реЛрдирд╛ рднрд╛рд╖рд╛ рдореЗрдВ рдХрд╛рдлреА рдмрдбрд╝рд╛ рдкреВрд░реНрдгрддрд╛ рдЫреЗрдж рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИред

рд╕рднреА 150 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореЗрд░реА рдирд╛рд╡ рдХрд╛ рдЖрдХрд╛рд░ рдФрд░ рдЖрдХрд╛рд░ рдХрд╛рдлреА рд╕рдорд╛рди рд╣реИ! рдЕрд╣реЛ!

рд╕реБрдкрд░рдХреНрд▓рд╛рд╕ рдореЗрдВ рдлрд╝реИрдХреНрдЯрд░реА рд╡рд┐рдзрд┐ рдЕрдкрдиреЗ рдЙрдкрд╡рд░реНрдЧреЛрдВ рдХреЗ рдирдП рдЙрджрд╛рд╣рд░рдг рд▓реМрдЯрд╛рддреА рд╣реИред рдореЗрд░реЗ рдХреЛрдб рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛рдо рдХрд░рддреА рд╣реИ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдбрд╛рд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

class Parent {
    public static deserialize(data: Object): any { ... create new instance ... }
    // Can't return a this type from statics! ^^^ :(
}

class Child extends Parent { ... }

let data = { ... };
let aChild: Child = Child.deserialize(data);
//           ^^^ Requires a cast as type cannot be inferred.

рдореИрдВ рдЖрдЬ рднреА рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛!

рдПрдХ рдлрд┐рдХреНрд╕рдЕрдк рд╕рдорд╛рдзрд╛рди рдмрдЪреНрдЪреЗ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдЖрдзрд╛рд░ рд╡рд░реНрдЧ рдХреЛ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рд╛рдорд╛рдиреНрдп рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдПрдХ рд╕рдорд╛рдзрд╛рди рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдЗрд╕ рд╕рдордп рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реВрдВ:

class Parent {
    static create<T extends Parent>(): T {
        let t = new this();

        return <T>t;
    }
}

class Child extends Parent {
    field: string;
}

let b = Child.create<Child>();

рдХреНрдпрд╛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдХрд╛рд░рдг рд╣реИ?

рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ рдпрд╣ рд╕реНрдЯреИрдЯрд┐рдХреНрд╕ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдореВрд▓ рд░реВрдк рд╕реЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдбреАрдУрдП рдмрдирд╛рддрд╛ рд╣реИ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВред рдореБрдЭреЗ рдЖрдЬ рддрдХ рдХрднреА рднреА рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдкрд░ рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдлрд┐рд░ рднреА рдореБрдЭреЗ рд╕реНрдЯреЗрдЯрд┐рдХреНрд╕ рдкрд░ рд╣рд░ рдХреБрдЫ рд╣рдлреНрддреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╢реБрд░реБрдЖрддреА рджрд┐рдиреЛрдВ рдореЗрдВ рд╕реНрдЯреЗрдЯрд┐рдХреНрд╕ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдЕрдВрддрд┐рдо рд░реВрдк рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЬрдм рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреА рдШреЛрд╖рдгрд╛ рдХреА рдЧрдИ рддреЛ рдореБрдЭреЗ рдмрд╣реБрдд рдЦреБрд╢реА рд╣реБрдИ, рдлрд┐рд░ рдмрд╛рдж рдореЗрдВ рдЬрдм рдпрд╣ рдорд╣рд╕реВрд╕ рд╣реБрдЖ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рддреЛ рдореБрдЭреЗ рдмрд╣реБрдд рдЦреБрд╢реА рд╣реБрдИред

рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рдмрд╣реБрдд рд╣реА рдмреБрдирд┐рдпрд╛рджреА рдФрд░ рдмреЗрд╣рдж рд╕рд╛рдорд╛рдиреНрдп рд╣реИред рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдлрд╝реИрдХреНрдЯрд░реА рд╡рд┐рдзрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:

class Animal
{
    static create(): this
    {
        return new this();
    }
}

class Bunny extends Animal
{
    hop()
    {
    }
}

Bunny.create().hop() // Type error!! Come on!!

рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдореИрдВ рдпрд╛ рддреЛ рдмрджрд╕реВрд░рдд рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗ рд░рд╣рд╛ рд╣реВрдВ рдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рдореЗрдВ static create() рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рди рд╣реЛрдирд╛ рднрд╛рд╖рд╛ рдореЗрдВ рдХрд╛рдлреА рдмрдбрд╝рд╛ рдкреВрд░реНрдгрддрд╛ рдЫреЗрдж рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИред

@ рдкреЙрд▓-рдЧреЛ рдореБрджреНрджрд╛ рдмрдВрдж рдирд╣реАрдВ рд╣реБрдЖ рд╣реИ ...?

@ рдкреЙрд▓-рдЧреЛ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рд╕реЗ рднреА рдирд┐рд░рд╛рд╢ рд╣реЛ рдЧрдпрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдиреАрдЪреЗ рд╕рдмрд╕реЗ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╕рдорд╛рдзрд╛рди рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкрд╢реБ рдЙрдкрд╡рд░реНрдЧ рдХреЛ рд╕реБрдкрд░.рдХреНрд░рд┐рдПрдЯ() рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЗрд╕рдХреЗ рдкреНрд░рдХрд╛рд░ рдкрд░ рдбрд╛рд▓рдирд╛ рд╣реЛрдЧрд╛ред рдХреЛрдИ рдмрдбрд╝реА рдмрд╛рдд рдирд╣реАрдВ рд╣реИ рдФрд░ рдпрд╣ рдПрдХ рд▓рд╛рдЗрдирд░ рд╣реИ рдЬрд┐рд╕реЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдЖрд╕рд╛рдиреА рд╕реЗ рд╣рдЯрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдХрдВрдкрд╛рдЗрд▓рд░, рдЗрдВрдЯреЗрд▓рд┐рдЬреЗрдВрд╕, рдФрд░ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдмрдиреА рд╕рднреА рдЦреБрд╢ рд╣реИрдВред

class Animal {
    public static create<T extends Animal>(): T {
        let TClass = this.constructor.prototype;
        return <T>( new TClass() );
    }
}

class Bunny extends Animal {    
    public static create(): Bunny {
        return <Bunny>super.create();
    }

    public hop(): void {
        console.log(" Hoppp!! :) ");
    }
}

Bunny.create().hop();

         \\
          \\_ " See? I am now a happy Bunny! "
           (')   " Don't be so hostile! "
          / )=           " :P "
        o( )_


@RyanCavanaugh рдУрд╣ ... рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдореИрдВрдиреЗ рдЗрд╕реЗ # 5862 рдХреЗ рд╕рд╛рде рднреНрд░рдорд┐рдд рдХрд░ рджрд┐рдпрд╛ ... рдпреБрджреНрдз рдХреБрд▓реНрд╣рд╛рдбрд╝реА рдЖрдХреНрд░рд╛рдордХрддрд╛ рдХреЗ рд▓рд┐рдП рдЦреЗрдж рд╣реИ :-)

@ рдерд┐рдВрдХ 7 рд╣рд╛рдВ ... рдЗрд╕рд▓рд┐рдП "рдмрджрд╕реВрд░рдд рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗрдирд╛ рдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рдореЗрдВ рд╕реНрдереИрддрд┐рдХ рдирд┐рд░реНрдорд╛рдг() рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗрдирд╛"ред рдпрд╣ рдмрд╣реБрдд рдХрдард┐рди рд╣реИ рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЬрдм рдЖрдк рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдбреЗрд╡рд▓рдкрд░ рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдВрддрд┐рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЙрди рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рдЯрд╛рдЗрдк рдХреА рдЧрдИ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╡реЗ рдЖрдкрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред

рд▓реЙрд▓ рдЖрдкрдХреЗ рдХреЛрдб рдХреЗ рддрд╣рдд рд╕рдм рдХреБрдЫ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдпрд╛рдж рдХрд┐рдпрд╛: рдбреА

рдореЗрд╣ рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдерд╛, рдПрдХ рдмрдиреА рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдерд╛ред

:+1: рдмрдиреА

:рдЦрд░рдЧреЛрд╢: :рджрд┐рд▓:

+1, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕реЗ рджреЗрдЦрдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ

рдХреНрдпрд╛ рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдХреЛрдИ рдЪрд░реНрдЪрд╛ рдЕрдкрдбреЗрдЯ рд╣реБрдИ рд╣реИ?

рдпрд╣ рд╣рдорд╛рд░реЗ рд╡рд┐рд╢рд╛рд▓ рд╕реБрдЭрд╛рд╡ рдмреИрдХрд▓реЙрдЧ рдкрд░ рдмрдирд╛ рд╣реБрдЖ рд╣реИред

рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдРрд╕реЗ рдкреИрдЯрд░реНрди рдореЗрдВ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ TS рднреА рдЕрдиреБрд╕рд░рдг рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ/рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЛрдб рд╕реЗ рдмрдЪрд╛рдПрдЧрд╛ред "рдореЙрдбрд▓ рдкреИрдЯрд░реНрди" рдПрдХ рд╕реБрдВрджрд░ рдорд╛рдирдХ рд╣реИ, рдореИрдВ рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЯреАрдПрд╕ рдХрд╛рдо рдХрд░реЗ рдХреНрдпреЛрдВрдХрд┐ рдЬреЗрдПрд╕ рдЗрд╕ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдЕрдиреНрдп рд╕рднреА рдХреЗ рд╕рдорд╛рди "рд╕реАрдЖрд░рдпреВрдбреА рдореЙрдбрд▓" рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рднреА рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ред рдореБрдЭреЗ рдЗрд╕реЗ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐рдпреЛрдВ рд╕реЗ рдЕрдзрд┐рдХ рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдкрд░ рдЪрд╛рд╣рд┐рдПред

рдпрд╣ #8164 рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рдкреНрд░рджрд╛рди рдХрд░реЗрдЧрд╛ред

рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ рдУрд╡рд░рд░рд╛рдЗрдб рдФрд░ рдЬреЗрдирд░рд┐рдХ рдХреЗ рд╕рд╛рде "рд╕рдорд╛рдзрд╛рди" рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡реЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рд╣рд▓ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ - рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд╣реЛрдиреЗ рдХрд╛ рдкреВрд░рд╛ рдЙрджреНрджреЗрд╢реНрдп рдЗрд╕ рддрд░рд╣ рдХреЗ рдУрд╡рд░рд░рд╛рдЗрдб / рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рд╕реЗ рдмрдЪрдирд╛ рд╣реИ рдФрд░ this рд░рд┐рдЯрд░реНрди рдХреЗ рд╕рд╛рде рд╕реНрдерд┐рд░рддрд╛ рдмрдирд╛рдирд╛ рд╣реИред рдкреНрд░рдХрд╛рд░ рдХреЛ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдореИрдВ Sequelize 4.0 рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдкрд┐рдВрдЧ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдпрд╣ рдПрдХ рдРрд╕реЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдЖрдк Model рд╡рд░реНрдЧ рдХреЛ рдЙрдк-рд╡рд░реНрдЧреАрдХреГрдд рдХрд░рддреЗ рд╣реИрдВред рдЙрд╕ рдореЙрдбрд▓ рд╡рд░реНрдЧ рдореЗрдВ рдЕрдирдЧрд┐рдирдд рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ рдЬреИрд╕реЗ findById() рдЖрджрд┐ред рдЬреЛ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ Model рдирд╣реАрдВ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдкрдХреЗ рдЙрдкрд╡рд░реНрдЧ, рдЙрд░реНрдл this рд╕реНрдерд┐рд░ рд╕рдВрджрд░реНрдн рдореЗрдВ:

abstract class Model {
    public static tableName: string;
    public static findById(id: number): this { // error: a this type is only available in a non-static member of a class or interface 
        const rows = db.query(`SELECT * FROM ${this.tableName} WHERE id = ?`, [id]);
        const instance = new this();
        for (const column of Object.keys(rows[0])) {
            instance[column] = rows[0][column];
        }
        return instance;        
    }
}

class User extends Model {
    public static tableName = 'users';
    public username: string;    
}

const user = User.findById(1); // user instanceof User

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рд╕реАрдХреНрд╡реЗрд▓рд╛рдЗрдЬрд╝ рдиреЛрдб рдХреЗ рд▓рд┐рдП _the_ ORM рд╣реИ рдФрд░ рдпрд╣ рджреБрдЦрдж рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЯрд╛рдЗрдк рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреА рдЬрд░реВрд░рдд рд╣реИред рд╣рд░ рдмрд╛рд░ рдЬрдм рдЖрдк рдЗрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ рдпрд╛ рдЙрдирдореЗрдВ рд╕реЗ рд╣рд░ рдПрдХ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдФрд░ super.method() рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рд╣реИред

рд╕рдВрдмрдВрдзрд┐рдд рдкреНрд░рдХрд╛рд░ рдпрд╣ рднреА рд╣реИ рдХрд┐ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдп рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реНрдХреЛрдВ рдХрд╛ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗ рд╣реИрдВ - рдХреБрдЫ рд╡рд┐рдзрд┐рдпрд╛рдВ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдЧреБрдгреЛрдВ рдХрд╛ рдПрдХ рд╡рд╕реНрддреБ рд╢рд╛рдмреНрджрд┐рдХ рд▓реЗрддреА рд╣реИрдВ рдЬрд┐рд╕реЗ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реНрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ рдХреЗрд╡рд▓ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИрдВред

рд╡рд┐рд╢реНрд╡рд╛рд╕ рдирд╣реАрдВ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрднреА рднреА рддрдп / рдЬреЛрдбрд╝рд╛ рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИ .....

рд╣рдо рдЗрд╕рдХрд╛ рдЕрдЪреНрдЫрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

declare class NSObject {
    init(): this;
    static alloc(): this;
}

declare class UIButton extends NSObject {
}

let btn: UIButton = UIButton.alloc().init();

рдпрд╣рд╛рдВ рдПрдХ рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рд╣реИ рдЬреЛ рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХрд╛рдо рдХрд┐рдпрд╛ (https://github.com/Microsoft/TypeScript/issues/9775 рд╕реЗ рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рдкрдХреНрд╖ рдореЗрдВ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛)

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдПрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдЙрдирдореЗрдВ this рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

class C<T> {
    constructor(
        public transformParam: (self: this) => T // not works
    ){
    }
    public transformMethod(self: this) : T { // works
        return undefined;
    }
}

рдЕрдкреЗрдХреНрд╖рд┐рдд: рдпрд╣ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред

рдПрдХ рд╕рдорд╕реНрдпрд╛ рдЬрд┐рд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ:

  • рдореЗрд░реЗ рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рдПрдкреАрдЖрдИ рдХреЛ рдЙрд╕реА рдХреЛрдб рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рдЕрдиреНрдп рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рдПрдкреАрдЖрдИ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдпрд╛ рддреЛ рдЖрдзрд╛рд░ рдмрдирд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛ:
class TheirFluentApi {
    totallyUnrelated(): TheirFluentApi {
        return this;
    }
}

class MyFluentApi<FluentApi> {
    constructor(
        public toNextApi: (self: this) => FluentApi // let's imagine it works
    ){
    }
    one(): FluentApi {
        return this.toNextApi(this);
    }
    another(): FluentApi {
        return this.toNextApi(this);
    }
}

// self based fluent API;
const selfBased = new MyFluentApi(this => this);
selfBased.one().another();

// foreign based fluent API:
const foreignBased = new MyFluentApi(this => new TheirFluentApi());
foreignBased.one().totallyUnrelated();

рдлреНрдпреВрдЪрд░-рдкреНрд░реВрдл рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб:

class Foo {

    foo() { }

    static create<T extends Foo>(): Foo & T {
        return new this() as Foo & T;
    }
}

class Bar extends Foo {

    bar() {}
}

class Baz extends Bar {

    baz() {}
}

Baz.create<Baz>().foo()
Baz.create<Baz>().bar()
Baz.create<Baz>().baz()

рдЗрд╕ рддрд░рд╣, рдЬрдм рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП this рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рддреЛ рдирдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб Baz.create() рдХреЗ рдмрдЬрд╛рдп Baz.create<Baz>() рд╣реЛрдЧрд╛ рдЬрдмрдХрд┐ рдкреБрд░рд╛рдирд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдб рдареАрдХ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред :рдореБрд╕реНрдХреБрд░рд╛рдУ:

рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реИ! рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдбреАрдПрдУ рдХреЗ рд▓рд┐рдП рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рд╕реНрдерд┐рд░ рддрд░реАрдХреЗ рд╣реИрдВ рдЬреЛ рдЙрджрд╛рд╣рд░рдг рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред рдЙрдирдореЗрдВ рд╕реЗ рдЕрдзрд┐рдХрддрд░ рдЖрдзрд╛рд░ рдбреАрдПрдУ рдкрд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реИрдВ, рдЬреИрд╕реЗ (рд╕рд╣реЗрдЬреЗрдВ, рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ, рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ рдЗрддреНрдпрд╛рджрд┐ ...)

рдореИрдВ рдХрд╣ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдХреБрдЫ рднреНрд░рдо рдкреИрджрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ this рдкреНрд░рдХрд╛рд░ рд╣реЛрдиреЗ рд╕реЗ рдЙрд╕ рд╡рд░реНрдЧ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рди рдХрд┐ рдХрдХреНрд╖рд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ (рдпрд╛рдиреА: typeof )ред

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЬреЗрдПрд╕ рдореЗрдВ, рдПрдХ рдкреНрд░рдХрд╛рд░ рдкрд░ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк this рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рд╡рд░реНрдЧ рд╣реЛрдЧрд╛ рдФрд░ рдЗрд╕рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рд╣реЛрдЧрд╛ ... рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЕрд╕рдВрдЧрдд рд╣реИред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рд▓реЛрдЧреЛрдВ рдХреЗ рдЕрдВрддрд░реНрдЬреНрдЮрд╛рди рдореЗрдВ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкрд╣рд▓реА рдЪреАрдЬ рдЬреЛ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ this рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рджреЗрдЦрддреЗ рд╕рдордп рдкреЙрдк рдЕрдк рд╣реЛрддреА рд╣реИ рд╡рд╣ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ ...

@shlomiassaf рдпрд╣ рдЕрд╕рдВрдЧрдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЬрдм рдЖрдк рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬреИрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд░реНрдЧ рдХреЛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реЛрдЧрд╛ред рдмрд┐рд▓реНрдХреБрд▓ рд╡реИрд╕рд╛ рд╣реА, рдЬрдм рдЖрдк рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ рдЗрд╕рдХрд╛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рддреЛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдЗрд╕рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реЛрдЧрд╛ (рдХрдХреНрд╖рд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг)ред рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛ рдХрдХреНрд╖рд╛ рдХреЛ рд╕реНрд╡рдпрдВ рд▓реМрдЯрд╛рддреА рд╣реИ, рдЙрд╕реЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

@felixfbecker рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдПрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдмрд┐рдВрджреБ рд╣реИ, рдЗрд╕ рддрд░рд╣ рдЖрдк рдЗрд╕реЗ рджреЗрдЦрдирд╛ рдЪреБрдирддреЗ рд╣реИрдВред

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ JS рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рддрд░реНрдХ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ:

class Example {
  myFunc(): this {
    return this; 
  }

  static myFuncStatic(): this {
    return this;   // this === Example
  }
}

new Example().myFunc() //  instanceof Exapmle === true
Example.myFuncStatic() // === Example

рдЕрдм, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд░рдирдЯрд╛рдЗрдо рдореЗрдВ this рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдмрдВрдзрд╛ рд╣реБрдЖ рд╕рдВрджрд░реНрдн рд╣реИ, рдпрд╣ рдареАрдХ рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬреИрд╕реЗ рдзрд╛рд░рд╛рдкреНрд░рд╡рд╛рд╣ рдПрдкреАрдЖрдИ рдореЗрдВ рдЗрдВрдЯрд░рдлреЗрд╕ рдФрд░ рдкреЙрд▓реАрдореЙрд░реНрдлрд┐рдХ рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддреА рд╣реИ, рдЬреЛ рдХрд┐ рдЬреЗрдПрд╕ рдХреЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рд╕рд╛рде рд╕рдВрд░реЗрдЦрд┐рдд рд╣реИ, рдПрдХ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ this рд▓реМрдЯрд╛рддрд╛ рд╣реИ рдЬреЛ рд╡реНрдпреБрддреНрдкрдиреНрди рд╡рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИред рд╕реБрд╡рд┐рдзрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдлрд┐рдХреНрд╕ рд╣реИред

рд╕рд╛рд░рд╛рдВрд╢ рдореЗрдВ:
рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк (рдЙрджрд╛рд╣рд░рдг) рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд this рд▓реМрдЯрдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╡рд┐рдзрд┐ рд╕реЗ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд╕ рдЖрдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИред

рдЙрд╕ рддрд░реНрдХ рдХреЛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реБрдП, this рд▓реМрдЯрд╛рдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╡рд┐рдзрд┐ рдЬрд┐рд╕реЗ рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░ (рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк) рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╕реЗ рдмрдВрдзреЗ рд╣реБрдП рд╕рдВрджрд░реНрдн рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЙрдореНрдореАрдж рдХреА рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдХрд┐ рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░ рд╣реИред

рдлрд┐рд░, рдХреЛрдИ рдкреВрд░реНрд╡рд╛рдЧреНрд░рд╣ рдирд╣реАрдВ, рдХреЛрдИ рд░рд╛рдп рдирд╣реАрдВ, рд╕рд╛рдзрд╛рд░рдг рддрдереНрдпред

рдЕрдВрддрд░реНрдЬреНрдЮрд╛рди рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдореИрдВ рдПрдХ рд╕реНрдерд┐рд░ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ this рд▓реМрдЯрд╛рдП рдЬрд╛рдиреЗ рдореЗрдВ рд╕рд╣рдЬ рдорд╣рд╕реВрд╕ рдХрд░реВрдВрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рднреАрддрд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдореИрдВ рд╣реВрдВред рджреВрд╕рд░реЗ рд▓реЛрдЧ рдЕрд▓рдЧ рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╣рдо рдЙрдиреНрд╣реЗрдВ рдЙрдирдХрд╛ рдЧрд▓рдд рдирд╣реАрдВ рдмрддрд╛ рд╕рдХрддреЗред

рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рджреЛрдиреЛрдВ рдХреЛ рдЯрд╛рдЗрдк рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдПрдХ рд╡рд░реНрдЧ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдЬреЛ рдХрдХреНрд╖рд╛ рдХреЛ рд╕реНрд╡рдпрдВ рд▓реМрдЯрд╛рддреА рд╣реИ (рдЗрд╕реЗ рдЯрд╛рдЗрдк рдХрд░реЗрдВ)ред рдЖрдкрдХрд╛ рддрд░реНрдХ рдЬреЗрдПрд╕ рдХреЗ рдирдЬрд░рд┐рдП рд╕реЗ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдпрд╣рд╛рдВ рд░рд┐рдЯрд░реНрди _types_ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рднрд╛рд╖рд╛ рдореЗрдВ рд░рд┐рдЯрд░реНрди рдЯрд╛рдЗрдк (рдпрд╣рд╛рдВ рдпрд╣) рдХреЗ рд░реВрдк рдореЗрдВ рдХреНрд▓рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣рдореЗрд╢рд╛ рдХреНрд▓рд╛рд╕ рдХрд╛ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╣реЛрддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд░реНрдЧ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЯрд╛рдЗрдкреЛрдлрд╝ рдСрдкрд░реЗрдЯрд░ рд╣реИред

@felixfbecker рдпрд╣ рдПрдХ рдФрд░ рдореБрджреНрджрд╛ рдЙрдард╛рддрд╛ рд╣реИ!

рдпрджрд┐ рдкреНрд░рдХрд╛рд░ this рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ, рддреЛ рдпрд╣ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЗ рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ this рдХреАрд╡рд░реНрдб рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рднрд┐рдиреНрди рд╣реИред return this рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ typeof this , рдЬреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдЬреАрдм рд╣реИ!

рдирд╣реАрдВ рдпрд╣ рдирд╣реАрдВред рдЬрдм рдЖрдк рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреИрд╕реЗ

getUser(): User {
  ...
}

рдЖрдк рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ _instance_ рд╡рд╛рдкрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, рди рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд░реНрдЧ (рдпрд╣реА рд╡рд╣ рд╣реИ рдЬреЛ typeof рдХреЗ рд▓рд┐рдП рд╣реИ)ред рдпрд╣ рд╣рд░ рдЯрд╛рдЗрдк рдХреА рдЧрдИ рднрд╛рд╖рд╛ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЯрд╛рдЗрдк рд╕реЗрдореЗрдиреНрдЯрд┐рдХреНрд╕ рд░рдирдЯрд╛рдЗрдо рд╕реЗрдореЗрдиреНрдЯрд┐рдХреНрд╕ рд╕реЗ рдмрд┐рд▓реНрдХреБрд▓ рдЕрд▓рдЧ рд╣реИрдВред

рдХреНрдпреЛрдВ рди this рдпрд╛ static рдХреАрд╡рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХ рдмрдЪреНрдЪреЗ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рд╣реЗрд░рдлреЗрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП func рдореЗрдВ рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░реЗрдВ?

class Model {
  static find():this[] {
    return [new this("prop")]; // or new static(...)
  }
}

class Entity extends Model {
  constructor(public prop:string) {}
}

Entity.find().map(x => console.log(x.prop));

рдФрд░ рдЕрдЧрд░ рд╣рдо рдЗрд╕рдХреА рддреБрд▓рдирд╛ JS рдореЗрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдпрд╣ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреНрдпрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

class Model {
  static find() { 
    return [new this] 
  }
}

class Entity extends Model {
  constructor(prop) {
    this.prop = prop;
  }
}

Entity.find().map(x => console.log(x.prop))

рдЖрдк рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ this рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЗрд╕ рдореБрджреНрджреЗ рдХреА рдкреВрд░реА рдЬрдбрд╝ рд╣реИред

@felixfbecker

рдЗрд╕ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЛ:

class Greeter {
    static getHandle(): this {
        return this;
    }
}

рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдиреЛрдЯреЗрд╢рди рд╕рд╣рдЬ рд╣реИ, рд▓реЗрдХрд┐рди рдЧрд▓рдд рд╣реИ рдпрджрд┐ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдореЗрдВ рдЯрд╛рдЗрдк this рдХреНрд▓рд╛рд╕ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╣реИред рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдореЗрдВ рдХреАрд╡рд░реНрдб this рдореЗрдВ typeof this $ рдХрд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ!

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ this _ рдЪрд╛рд╣рд┐рдП_ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ, рди рдХрд┐ рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдХрд╛рд░ рд╕реЗ рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдВрджрд░реНрдн рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ( typeof X ) рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рдирд╣реАрдВ ( instancetypeof X ?)

@xealot рдареАрдХ рд╣реИ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп $ static рдХреАрд╡рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрдпреЛрдВ рди рдХрд░реЗрдВ $ this ? рд▓реЗрдХрд┐рди рдЬреЗрдПрд╕ рд╕реНрдерд┐рд░ рд╕рдВрджрд░реНрдн рдореЗрдВ this рдЕрднреА рднреА рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред

@izatop рд╣рд╛рдБ, рдЙрддреНрдкрдиреНрди рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ (рдареАрдХ рд╕реЗ рдпрд╛ рдЕрдиреБрдЪрд┐рдд рддрд░реАрдХреЗ рд╕реЗ)ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИред рд╢рд┐рдХрд╛рдпрдд рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рднрд╛рд╖рд╛ рдЗрд╕ рдкреИрдЯрд░реНрди рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддреА рд╣реИ, рдпрд╣ рд╣реИ рдХрд┐ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рдЖрдк рдЗрд╕ рдкреИрдЯрд░реНрди рдХреЗ рд╕рд╛рде рдЯрд╛рдЗрдк рд╕реБрд░рдХреНрд╖рд╛ рдХреЛ рдмрдирд╛рдП рдирд╣реАрдВ рд░рдЦ рд╕рдХрддреЗ рдХреНрдпреЛрдВрдХрд┐ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдкрд░ рдкреЙрд▓реАрдореЙрд░реНрдлрд┐рдХ this рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ static рдХреАрд╡рд░реНрдб рдФрд░ constructor рдХреЗ рд╕рд╛рде рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╡рд░реНрдЧ рд╡рд┐рдзрд┐рдпрд╛рдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред

рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рд▓рд┐рдВрдХ

@LPGhatguy рд▓реЗрдХрд┐рди рдЖрдкрдиреЗ рдореЗрд░реА рдкрд┐рдЫрд▓реА рдЯрд┐рдкреНрдкрдгреА рдкрдврд╝реА, рд╣реИ рдирд╛ ?! рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ User рдХреЗ рд╕рд╛рде рдХреЛрдИ рд╡рд┐рдзрд┐ рд╣реИ, рддреЛ рдЖрдк return new User(); рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, рди рдХрд┐ return User; ред рдЙрд╕реА рддрд░рд╣ this рдХреЗ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдХрд╛ рдорддрд▓рдм рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдореЗрдВ return new this(); $ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЧреИрд░ рд╕реНрдереИрддрд┐рдХ рддрд░реАрдХреЛрдВ рдореЗрдВ рдпрд╣ рдЕрд▓рдЧ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ this рд╣рдореЗрд╢рд╛ рдПрдХ рд╡рд╕реНрддреБ рд╣реИ, рдЖрдк рдЗрд╕реЗ рддреБрд░рдВрдд рдЪрд╛рд▓реВ рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗред рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ, рд╣рдо рдореВрд▓ рд░реВрдк рд╕реЗ рд╕рднреА рд╕рд╣рдордд рд╣реИрдВ рдХрд┐ typeof рдХреЗ рдХрд╛рд░рдг рдпрд╣ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣реИ рдФрд░ TS рдореЗрдВ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреА рдмрд╣реБрдд рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

@xealot рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрд╣реБрд░реВрдкреА this рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рдлрд┐рд░ рднреА рдореИрдВ рдЖрдкрд╕реЗ рдкреВрдЫреВрдВрдЧрд╛ рдХрд┐ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ TS рдореЗрдВ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдП?

рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд╕рднреА рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдорд╛рди рдкреНрд░рдгрд╛рд▓реА рдХреЗ рд╕реНрдорд╛рд░реНрдЯ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд╕рд╛рде рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдореЗрдВ this: рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдордЬрд╛ рдЖрддрд╛ рд╣реИ рдЯрд╛рдЗрдкрд┐рдВрдЧред рдпрд╣ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдкрдардиреАрдп рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдмрдЪреНрдЪреЛрдВ рдХреА рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ@2.0.0 . рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ

рдирд┐рдореНрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ ;

// IModelClass is just here to describe an instanciator
// since we can't use typeof T (unfortunately) with
// the generic type system.
interface IModelClass<T extends Model> {
  new (...a: any[]): T

  // unfortunately, we have to put here again all the typing information
  // of the static members (without static, since we are describing a class, not an instance)

  some_member: string
  create<T extends Model>(this: IModelClass<T>): T
}

class Model {

  // Here we use this with the IModel<T> to force the
  // type system to use T as our current caller.

  static some_member: string

  // When we call Dog.create() below, T is thus resolved
  // to Dog *and stays that way*
  // If typeof worked on generic types (it doesn't), we could have defined this method
  // instead as 
  // static create<T extends Model>(this: typeof T): T { ... }
  static create<T extends Model>(this: IModelClass<T>): T {
    return new this() // whatever you fancy here
  }
}

class Dog extends Model {
  bark() { }
}

class Cat extends Model {
  meow() { }
}

// Everything should be typed here, and we didn't have to redefine static methods
// in Dog nor Cat
let dog = Dog.create()
dog.bark()
let cat = Cat.create()
cat.meow()

@ceymard рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ this рдХреНрдпреЛрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ?

рдпрд╣ https://github.com/Microsoft/TypeScript/issues/3694 рдХреЗ рдХрд╛рд░рдг рд╣реИ рдЬрд┐рд╕реЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ 2.0.0 рдХреЗ рд╕рд╛рде рднреЗрдЬрд╛ рдЧрдпрд╛ рдерд╛ рдЬреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ (рдЗрд╕ рдкреНрд░рдХрд╛рд░ this рдмрд┐рдирд╛ рдЙрдирдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рд╕рдорд╕реНрдпрд╛рдУрдВ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЧрд▓рдд рдЙрдкрдпреЛрдЧ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП)

рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╣рдо рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдордЬрд╝реЗрджрд╛рд░ рд╕рд╛рдорд╛рди рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреИрд╕реЗ рдХрд┐ рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП this рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХреЛ "рдорджрдж" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред (рдЖрдЗрдореЙрдбрд▓) рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ (рдХреБрддреНрддрд╛, рдпрд╛ рдмрд┐рд▓реНрд▓реА)ред рдпрд╣ рддрдм T рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рдХрд╛ "рдЕрдиреБрдорд╛рди" рд▓рдЧрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЯрд╛рдЗрдк рдХрд░рддрд╛ рд╣реИред

(рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ this рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрдВрдкрд╛рдЗрд▓рд░ рджреНрд╡рд╛рд░рд╛ рд╕рдордЭрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ _special_ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ, рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдПрдХ рдФрд░ рдирд╣реАрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ)

рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдерд╛ рдХрд┐ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ <this extends Whatever> рдЬреИрд╕рд╛ рдХреБрдЫ рдерд╛ред рддреЛ рдпрд╣ рддрдм рднреА рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдЬрдм create() рдореЗрдВ рдЕрдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рд╣реЛрдВ?

рдмрд┐рд▓реНрдХреБрд▓

рдореИрдВ рдпрд╣ рднреА рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдпрд╣ рдмрд┐рд▓реНрдб-рдЗрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред
рдЬрдм рдЖрдк рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП Array рдЙрдкрд╡рд░реНрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЙрдкрд╡рд░реНрдЧ рдХреА from() рд╡рд┐рдзрд┐ рдЙрдкрд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд▓реМрдЯрд╛рдПрдЧреА, рди рдХрд┐ Array ред

class Task {}
class TaskList extends Array<Task> {
  public execute() {}
}
// actually returns instance of TaskList at runtime
const tasks = TaskList.from([new Task()])
tasks.execute() // error, method execute does not exist on type Array

рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдХреЛрдИ рдЕрдкрдбреЗрдЯ? рдпрд╣ рдлреАрдЪрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рд╛рде рдореЗрд░реА рдЯреАрдо рдХреЗ рдЕрдиреБрднрд╡ рдХреЛ рдХрд╛рдлреА рдмрдврд╝рд╛ рджреЗрдЧрд╛ред

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдмрд▓реНрдХрд┐ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдУрдЖрд░рдПрдо рдореЗрдВ рдЖрдорддреМрд░ рдкрд░ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ рдкреИрдЯрд░реНрди рд╣реИ рдФрд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рдХрдВрдкрд╛рдЗрд▓рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореИрдВ рдХрд╛рдЙрдВрдЯрд░ рддрд░реНрдХ рдХреЗ рдЦрд┐рд▓рд╛рдл рдХреБрдЫ рдХрд╛рдЙрдВрдЯрд░ рддрд░реНрдХ рдЙрдард╛рдКрдВрдЧрд╛ред

рдЬреИрд╕рд╛ рдХрд┐ @shlomiassaf рдиреЗ рдмрддрд╛рдпрд╛, рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдореЗрдВ this рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рд╕реЗ рднреНрд░рдо рдкреИрджрд╛ рд╣реЛрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ this рдХрд╛ рдорддрд▓рдм рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдФрд░ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐ рдореЗрдВ рдЕрд▓рдЧ рдЪреАрдЬ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, this рдЯрд╛рдЗрдк рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рдФрд░ this рдореЗрдердб рдмреЙрдбреА рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╢рдмреНрджрд╛рд░реНрде рд╣реИрдВред рд╣рдо рдирдП рдХреАрд╡рд░реНрдб рдХреЛ рдкреЗрд╢ рдХрд░рдХреЗ рдЗрд╕ рднреНрд░рдо рд╕реЗ рдмрдЪ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рдирдП рдХреАрд╡рд░реНрдб рдХреА рд▓рд╛рдЧрдд рдЕрдзрд┐рдХ рд╣реЛрддреА рд╣реИред

рдФрд░ рд╡рд░реНрддрдорд╛рди рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рд╣реИред @ceymard рдкрд╣рд▓реЗ рд╣реА рджрд┐рдЦрд╛ рдЪреБрдХрд╛ рд╣реИ рдХрд┐ . рдФрд░ рдореИрдВ рдЙрдирдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕реНрдереИрддрд┐рдХ рд╡рд┐рдзрд┐ рдХреЗ рд░рдирдЯрд╛рдЗрдо рд╕рд┐рдореЗрдВрдЯрд┐рдХ рдХреЛ рдкрдХрдбрд╝ рд▓реЗрддрд╛ рд╣реИред рдЗрд╕ рдХреЛрдб рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

class A {
  constructor() {}
  static create<T extends A>(this: {new (): T}) {} // constructor signature is exactly the same as A's
}

class B extends A {
  constructor(a: number) {
    super()
  }
}

B.create() // correctly trigger compile error here

рдпрджрд┐ рдмрд╣реБрд░реВрдкреА рдпрд╣ рд╕рдорд░реНрдерд┐рдд рд╣реИ, рддреЛ рд╕рдВрдХрд▓рдХ рдХреЛ class B extends A рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рддреЛрдбрд╝рдиреЗ рд╡рд╛рд▓рд╛ рдмрджрд▓рд╛рд╡ рд╣реИред

@HerringtonDarkholme рдореБрдЭреЗ рднреНрд░рдо рдирд╣реАрдВ рджрд┐рдЦ рд░рд╣рд╛ рд╣реИ, рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ this рдареАрдХ рд╡рд╣реА рд╣реИ рдЬреЛ рдореИрдВ return new this() рд╕реЗ рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реВрдВред рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рд╣рдо рдЙрд╕рдХреЗ рд▓рд┐рдП self рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рдЕрдиреНрдп рдХреАрд╡рд░реНрдб (рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛) рдХреЛ рдкреЗрд╢ рдХрд░рдирд╛ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд▓рдЧрддрд╛ рд╣реИред рд╣рдо рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдПрдХрдорд╛рддреНрд░ (рд▓реЗрдХрд┐рди рдмрдбрд╝реА) рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдореЗрдВ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИред

рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ "рдПрдиреНрд╣рд╛рдВрд╕реНрдб рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ" рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рд╕рдЪ рдирд╣реАрдВ рд╣реИ, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдХреЛрдб рдХреЗ рд▓рд┐рдП рд▓рд╛рдЦреЛрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЬрдЯрд┐рд▓ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЗрд╕реЗ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдареАрдХ рд╣реИ рдФрд░ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

рдореЗрдердб рдмреЙрдбреА рдореЗрдВ this this рдкреНрд░рдХрд╛рд░ рд╕реЗ рдЕрд▓рдЧ рдХреНрдпреЛрдВ рд╣реИ?
рдпрд╣ рдХреЛрдб рд╡рд┐рдлрд▓ рдХреНрдпреЛрдВ рд╣реЛрддрд╛ рд╣реИ? рдЖрдк рдЗрд╕реЗ рдПрдХ рдирдП рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХреЛ рдХреИрд╕реЗ рд╕рдордЭрд╛ рд╕рдХрддреЗ рд╣реИрдВ?

class A {
  static create(): this {
     return this
  }
}

рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдПрдХ рд╕реБрдкрд░рд╕реЗрдЯ рдЗрд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓ рдХреНрдпреЛрдВ рд╣реЛрдЧрд╛?

class A {
  static create() {
    return new this()
  }
}

abstract class B extends A {}

рд╕рдЪ рд╣реИ, рддрдм рд╣рдореЗрдВ рдПрдХ рдФрд░ рдЦреЛрдЬрд╢рдмреНрдж рдкреЗрд╢ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред self рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╛ рд╢рд╛рдпрдж instance

@HerringtonDarkholme рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдЗрд╕реЗ рдПрдХ рдирд╡рд╛рдЧрдВрддреБрдХ рдХреЛ рдХреИрд╕реЗ рд╕рдордЭрд╛рддрд╛ рд╣реВрдВред
рдЬрдм рддреБрдо рдХрд░реЛрдЧреЗ

class A {
  static whatever(): B {
    return new B();
  }
}

B рдХрд╛ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЖрдкрдХреЛ B рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдХрдХреНрд╖рд╛ рдХреЛ рд╕реНрд╡рдпрдВ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

class B {
 static whatever(): typeof B {
   return B;
 }
}

рдЕрдм, рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рддрд░рд╣, рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдореЗрдВ this рд╡рд░реНрдЧ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдореЗрдВ this рдХреЗ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдХрдХреНрд╖рд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

class A {
  static whatever(): this {
    return new this();
  }
}

рдпрджрд┐ рдЖрдк рдХрдХреНрд╖рд╛ рдХреЛ рд╕реНрд╡рдпрдВ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ typeof this рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

class A {
  static whatever(): typeof this {
    return this;
  }
}

рдареАрдХ рдЗрд╕реА рддрд░рд╣ рдЯреАрдПрд╕ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЯрд╛рдЗрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВ, рддреЛ TS рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рд╣реА рдЯрд╛рдЗрдк рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ typeof рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рддрдм рдореИрдВ рдкреВрдЫреВрдВрдЧрд╛ рдХрд┐ рд╡рд┐рдзрд┐ рдирд┐рдХрд╛рдп рдореЗрдВ this рдХрд╛ рд╕рдорд╛рди рдЕрд░реНрде рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ this рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдореЗрдердб рдХреЗ рдЯрд╛рдЗрдк рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЕрд░реНрде 'рд╕рдВрдмрдВрдзрд┐рдд рдореЗрдердб рдмреЙрдбреА' рдореЗрдВ this рдХреЗ рд╕рд╛рде рд╕рдорд╛рди рд╣реИ, рддреЛ рдпрд╣ рд╕реНрдЯреИрдЯрд┐рдХ рдореЗрдердб рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реИ?

рд╣рдо рдПрдХ рджреБрд╡рд┐рдзрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рддреАрди рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ:

  1. this рдмрдирд╛рдиреЗ рдХрд╛ рдорддрд▓рдм рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЪреАрдЬреЗрдВ рд╣реИрдВ (рднреНрд░рдо)
  2. self рдпрд╛ static . рдЬреИрд╕реЗ рдирдП рдХреАрд╡рд░реНрдб рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрдВ
  3. рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рдЕрдзрд┐рдХ рдЕрдЬреАрдм рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдиреЛрдЯреЗрд╢рди рд▓рд┐рдЦрдиреЗ рджреЗрдВ (рдХреБрдЫ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░реЗрдВ)

рдореИрдВ рддреАрд╕рд░рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕реНрдереИрддрд┐рдХ рд╡рд┐рдзрд┐ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд░рдирдЯрд╛рдЗрдо рд╕рд┐рдореЗрдВрдЯрд┐рдХ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИред
рдпрд╣ рд╕рд╛рдЗрдЯ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЙрдкрдпреЛрдЧ рд╕рд╛рдЗрдЯ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рднреА рд╕реНрдкреЙрдЯ рдХрд░рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд, рдЗрд╕ рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ, рддреНрд░реБрдЯрд┐ B.create рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдХреА рдЧрдИ рд╣реИ, рди рдХрд┐ class B extends A рдореЗрдВред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рд╛рдЗрдЯ рддреНрд░реБрдЯрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдзрд┐рдХ рд╕рдЯреАрдХ рд╣реИред (рдорд╛рди рд▓реЗрдВ рдХрд┐ рдЖрдк рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдШреЛрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ this рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╣реИ рдФрд░ рдлрд┐рд░ рдПрдХ рд╕рд╛рд░ рдЙрдкрд╡рд░реНрдЧ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ)ред

рдФрд░, рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд, рдЗрд╕реЗ рдирдИ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рднрд╛рд╖рд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╡рд░реАрдпрддрд╛ рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддреА рд╣реИред рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХрд╛ рдПрдХ рдФрд░ рд╡рд┐рд╕реНрддреГрдд рдкреНрд░рд╕реНрддрд╛рд╡ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдореБрджреНрджреЗ рд╣реИрдВ рдЬреИрд╕реЗ рдЕрдореВрд░реНрдд рд╡рд░реНрдЧ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ, рдЙрдкрд╡рд░реНрдЧ рдЕрд╕рдВрдЧрдд рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдФрд░ рддреНрд░реБрдЯрд┐ рд░рд┐рдкреЛрд░реНрдЯ рд░рдгрдиреАрддрд┐рдпрд╛рдБред

@HerringtonDarkholme рдХреНрдпреЛрдВрдХрд┐ рдЙрджрд╛рд╣рд░рдг рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд░рдирдЯрд╛рдЗрдо this рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╣реИ рдФрд░ рдХреНрд▓рд╛рд╕ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рднреНрд░рдо рдХреА рдХреЛрдИ рдЬрдЧрд╣ рдирд╣реАрдВ рд╣реИред рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд░ this рд╡рд╕реНрддреБрддрдГ рд░рдирдЯрд╛рдЗрдо this рд╣реИ, рдХреЛрдИ рдЕрдиреНрдп рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИред рдЬрдмрдХрд┐ рд╕реНрдерд┐рд░ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдХрд┐рд╕реА рднреА рд╡рд╕реНрддреБ рдЙрдиреНрдореБрдЦ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдореЗрдВ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рд╡рд░реНрдЧ рдПрдиреЛрдЯреЗрд╢рди рдХреА рддрд░рд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ: рдЗрд╕реЗ рдХрдХреНрд╖рд╛ рдХреЗ рд╕рд╛рде рдПрдиреЛрдЯреЗрдЯ рдХрд░реЗрдВ, рдФрд░ рдЖрдк рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЯреАрдПрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рднреА рд╡рд╕реНрддреБрдПрдВ рд╣реИрдВ, рдЗрд╕реЗ typeof рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рдЯрд╛рдЗрдк рдХрд░реЗрдВ рдФрд░ рдЖрдкрдХреЛ рд╢рд╛рдмреНрджрд┐рдХ рд╡рд░реНрдЧ рд╡рд╛рдкрд╕ рдорд┐рд▓ рдЬрд╛рдПрдЧрд╛ред

рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдпрд╣ рд╢рд╛рдпрдж рддрдм рдФрд░ рдЕрдзрд┐рдХ рд╕реБрд╕рдВрдЧрдд рд░рд╣рд╛ рд╣реЛрдЧрд╛ рдЬрдм рдЙрдиреНрд╣реЛрдВрдиреЗ рд╕реНрдерд┐рд░ рдорд╛рдорд▓реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд┐рдП this рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╣рдореЗрд╢рд╛ рдЙрджрд╛рд╣рд░рдг рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП typeof this рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рд▓реЗрдХрд┐рди рд╡рд╣ рдирд┐рд░реНрдгрдп рддрдм рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЕрдм рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдФрд░ рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛ рдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рднреНрд░рдо рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЬрдЧрд╣ рдирд╣реАрдВ рдЫреЛрдбрд╝рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЙрджрд╛рд╣рд░рдг рдХреЗ рддрд░реАрдХреЛрдВ рдореЗрдВ this рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд, рдЬреЛ рдПрдХ рд╕реНрдерд┐рд░ рдкреНрд░рдХрд╛рд░ рдФрд░ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдХрд╛рд░ рд╣реИ), рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЙрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЕрд▓рдЧ рд╣реИ рдФрд░ рдХрд┐рд╕реА рдХреЛ рднреА рднреНрд░рдорд┐рдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

рдареАрдХ рд╣реИ, рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рднреА this рд╕реЗ рднреНрд░рдорд┐рдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЕрдореВрд░реНрдд рд╡рд░реНрдЧ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ?

рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рд╕реНрдерд┐рд░рддрд╛ рдХреБрдЫ рд╣рдж рддрдХ рдордирдорд╛рдиреА рд╣реИред рдХрд┐рд╕реА рднреА рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЧреБрдг рдФрд░ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рдпрджрд┐ рдЗрд╕реЗ new рдХреЗ рд╕рд╛рде рднреА рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрди рдЧреБрдгреЛрдВ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ static рдХрд╣рддреЗ рд╣реИрдВред рдЕрдм рдЗрд╕ рд╕рдореНрдореЗрд▓рди рдХреЛ рдИрд╕реАрдПрдордПрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдордЬрдмреВрддреА рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

@HerringtonDarkholme рдЖрдк рдирд┐рд╕реНрд╕рдВрджреЗрд╣ рд╕рд╣реА рд╣реИрдВ рдХрд┐ this рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рднреНрд░рдо рдкреИрджрд╛ рд╣реЛрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЪреВрдВрдХрд┐ this рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдХреБрдЫ рднреА рдЧрд▓рдд рдирд╣реАрдВ рд╣реИ, рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдареАрдХ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдЬрдм рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рдЖрдкрдХреЗ рд╕реВрдХреНрд╖реНрдо рд▓рд╛рдЧрдд рд▓рд╛рдн рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдПред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ this рдХрдо рд╕реЗ рдХрдо рдЦрд░рд╛рдм рд╡рд┐рдХрд▓реНрдк рд╣реИред

рдореИрдВрдиреЗ рдЕрднреА рдЕрдкрдиреА рдореВрд▓ рдкреЛрд╕реНрдЯ рд╕реЗ рдЗрд╕ рдзрд╛рдЧреЗ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ, рдореБрдЭреЗ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╢рд╛рдпрдж рдпрд╣ рдереЛрдбрд╝рд╛ рд╕рд╛ рдЯреНрд░реИрдХ рд╣реЛ рдЧрдпрд╛ рд╣реИред

рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрдЪреНрдЫрд╛ рд╣реИ рдХрд┐ this рдЯрд╛рдЗрдк рдПрдиреЛрдЯреЗрд╢рди рдкреЙрд▓реАрдореЙрд░реНрдлрд┐рдХ рд╣реЛ рдЬрдм рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп/рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВред @shlomiassaf рдФрд░ @HerringtonDarkholme рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ static рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдЙрджрд╛рд╣рд░рдг рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдпрд╣ рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рдЗрд░рд╛рджрд╛ рдирд╣реАрдВ рд╣реИред

рднрд▓реЗ рд╣реА рдЗрд╕реЗ рдЕрдХреНрд╕рд░ рдРрд╕рд╛ рдирд╣реАрдВ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдПрдХ рд╡рд░реНрдЧ рдХрд╛ рдирд┐рд░реНрдорд╛рддрд╛ рд╕реНрдерд┐рд░ рд╣реЛрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг (рдЬрд┐рд╕реЗ рдореИрдВ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рджреЛрдмрд╛рд░рд╛ рдкреЛрд╕реНрдЯ рдХрд░реВрдВрдЧрд╛) рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ this рдШреЛрд╖рд┐рдд рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЗ рдкреНрд░рдХрд╛рд░ рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рдЬреЗрдиреЗрд░рд┐рдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП this рдШреЛрд╖рд┐рдд рдХрд░ рд░рд╣рд╛ рд╣реИ .

рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рдХрд┐ this рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдкрд░ рддреБрд░рдВрдд рдЧрдгрдирд╛ рдХреА рдЬрд╛рдП, рд▓реЗрдХрд┐рди рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдореЗрдВред

// START LIBRARY CODE
// Constrains the constructor to one that creates things that extend from BaseModel
interface ModelConstructor<T extends BaseModel> {
    new(fac: ModelAPI<T>): T;
}

class ModelAPI<T extends BaseModel> {
    // skipping the use of a ModelConstructor in favor of typeof does not work
    // constructor(private modelType: typeof T) {}
    constructor(private modelType: ModelConstructor<T>) {}

    create() {
        return new this.modelType(this);
    }
}

class BaseModel {
    // This is where "polymorphic `this`" in static members matters. We are 
    // trying to say that the ModelAPI should create instances of whatever 
    // the *current* class is, not the BaseModel class. Much like it would 
    // at runtime.
    constructor(private fac: ModelAPI<this>) {}

    reload() {
        // `reload()` returns a new instance of type Any, incorrect
        return this.fac.create();
    }
}
// END LIBRARY CODE

// START APPLICATION CODE
// Create a custom model class with custom behavior
class Model extends BaseModel {}

// Create an instance of the model API that produces my custom type
let api = new ModelAPI<Model>(Model);  // ModalAPI should be able to infer "<Model>" from the constructor?
let modelInst = api.create();  // Returns type of Model, correct
let reset = modelInst.reload();  // Returns type of Any, incorrect
// END APPLICATION CODE

рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рднреА рдЬреЛ рд╕реЛрдЪрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд╣реИ, рдареАрдХ рд╣реИ, рдпрд╣ рд╕реБрдкрд░ рд╕реНрдЯреНрд░реЗрдЯ рдлреЙрд░рд╡рд░реНрдб рдирд╣реАрдВ рд╣реИ, рдореИрдВ рд╕рд╣рдордд рд╣реВрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, this рдХрд╛ рдЙрдкрдпреЛрдЧ BaseModel рдХреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕реНрдерд┐рд░ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдмрд╛рдж рдореЗрдВ рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╕реНрдердЧрд┐рдд рдЙрдкрдпреЛрдЧ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпрд╛рдБ (рдХрдиреНрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╕рд╣рд┐рдд) рдЙрд╕ рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреА рд╣реИрдВред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд░рдирдЯрд╛рдЗрдо рдкрд░ рдпрд╣ рд╕рдм рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐ рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдЗрд╕ рд╡рд┐рд╢реЗрд╖ рдкреИрдЯрд░реНрди рдХреЛ рдореЙрдбрд▓рд┐рдВрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрде рд╣реИред рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреИрдЯрд░реНрди рдХреЛ рдореЙрдбрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рдЕрдХреНрд╖рдорддрд╛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рдЦреБрд▓реЗ рд╣реЛрдиреЗ рдХрд╛ рдЖрдзрд╛рд░ рд╣реИред

рдХреНрд╖рдорд╛ рдХрд░реЗрдВ рдпрджрд┐ рдпрд╣ рдПрдХ рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЯрд┐рдкреНрдкрдгреА рд╣реИ, рдЬреЛ рдЬрд▓реНрджрдмрд╛рдЬреА рдореЗрдВ рд▓рд┐рдЦреА рдЧрдИ рд╣реИред

@xealot рдореБрдЭреЗ рдЖрдкрдХреА рдмрд╛рдд рд╕рдордЭ рдореЗрдВ рдЖ рдЧрдИ, рд▓реЗрдХрд┐рди рдЕрдиреНрдп рдореБрджреНрджреЗ рдЬреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реНрдереИрддрд┐рдХ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдкреЙрд▓реАрдореЙрд░реНрдлрд┐рдХ this рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВ, рдЗрд╕ рдПрдХ рдХреЗ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдмрдВрдж рд╣реЛ рдЧрдПред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЯреАрдПрд╕ рдореЗрдВ рдлрд┐рдХреНрд╕ рджреЛрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред

рдЖрдкрдХрд╛ рд╕рдЯреАрдХ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдХреНрдпрд╛ рд╣реИ? рд╢рд╛рдпрдж рдпрд╣реА 'рд╕рдорд╛рдзрд╛рди' рдХрд╛рдлреА рд╣реИред

рдореИрдВ рдЗрд╕реЗ рд╕рдлрд▓рддрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдХрд╕реНрдЯрдо рдУрдЖрд░рдПрдо рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ
рд▓реЗ рдЬреНрдпреВред 20 рдЕрдХреНрдЯреВрдмрд░ 2016 19:15, рдЯреЙрдо рдорд╛рд░рд┐рдпрд╕ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди @github.com a
рдЗрдХреНрд░рд┐рдЯ:

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдХрд╛рдлреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
рдУрдЖрд░рдПрдо рдореЗрдВ рдкреИрдЯрд░реНрди рдФрд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдХреЛрдб рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрд▓рдЧ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддреЗ рд╣реИрдВ
рдХрдВрдкрд╛рдЗрд▓рд░ рдФрд░ рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

-
рдЖрдк рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ, рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/Microsoft/TypeScript/issues/5863#issuecomment -255169194,
рдпрд╛ рдереНрд░реЗрдб рдХреЛ рдореНрдпреВрдЯ рдХрд░реЗрдВ
https://github.com/notifications/unsubscribe-auth/AAtAoRHc45B386xdNhuCLB8iW6i82e7Uks5q16GzgaJpZM4GsmOH
.

@ceymard рдФрд░ @HerringtonDarkholme рдХреЛ рдзрдиреНрдпрд╡рд╛рджред

static create<T extends A>(this: {new (): T}) { return new this(); } рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдЪрд╛рд▓ рдЪрд▓реА

рдпрд╣ рдкрд╣рд▓реА рдирдЬрд░ рдореЗрдВ static create(): this { return new this(); } рд╕реЗ рдЕрдзрд┐рдХ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИ рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо, рдпрд╣ рд╕рд╣реА рд╣реИ! рдпрд╣ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ this рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рдЯреАрдХ рд░реВрдк рд╕реЗ рдХреИрдкреНрдЪрд░ рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреА рдЬрд╛ рд╕рдХрддреА рд╣реИ, рднрд▓реЗ рд╣реА рдпрд╣ рд╕рдмрд╕реЗ рдКрдкрд░ рдпрд╛ рдЯрд┐рдкреНрдкрдгреА рдЖрджрд┐ рди рд╣реЛред рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк рддрд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрд╣реБрдд рдкрд░реЗрд╢рд╛рди рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

let u = User.create<User>();

рдЬрдм рдРрд╕рд╛ рдХрд░рдирд╛ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рд╕рдВрднрд╡ рд╣реЛ:

let u = User.create();

рдФрд░ рдпрд╣ рдЕрдирд┐рд╡рд╛рд░реНрдп рд╣реИ рдХрд┐ рд╕реНрдереИрддрд┐рдХ рдХрднреА-рдХрднреА рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред

рдореЗрд░реЗ рдкрд╛рд╕ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдФрд░ рд╡рд┐рдЪрд╛рд░ рдерд╛ рдХрд┐ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдпреЛрдВ рдореЗрдВ this рдкреНрд░рдХрд╛рд░ рд╡рд░реНрдЧ рдХреЗ рд╕реНрдерд┐рд░ рдкрдХреНрд╖ рдпрд╛ рдЙрджрд╛рд╣рд░рдг рдкрдХреНрд╖ рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред this рд╕реНрдерд┐рд░ рдкрдХреНрд╖ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╣ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдореЗрдВ рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд░рдирдЯрд╛рдЗрдо рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЖрдк this.prototype рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреНрд░рдХрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

abstract class Model {
  static findAll(): Promise<this.prototype[]>
}

class User extends Model {}

const users: User[] = await User.findAll();

рдпрд╣ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдЕрдиреБрд░реВрдк рд╣реЛрдЧрд╛ред this рд╡рд░реНрдЧ рд╡рд╕реНрддреБ рд╣реА рд╣реИ, рдФрд░ рдЙрджрд╛рд╣рд░рдг this.prototype рдкрд░ рд╣реИред рдпрд╣ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдореИрдк рдХрд┐рдП рдЧрдП рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рдорд╛рди рдореИрдХреЗрдирд┐рдХ рд╣реИ, рдЬреЛ this['prototype'] рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред

рдЙрд╕реА рддрд░рд╣ рдЖрдк this.constructor (рдореИрдВ рдЗрд╕ рдПрдЯреАрдПрдо рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╕реЛрдЪ рд╕рдХрддрд╛) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рджрд╕реНрдпреЛрдВ рдореЗрдВ рд╕реНрдерд┐рд░ рдкрдХреНрд╖ рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред

рдореИрдВ рдпрд╣ рднреА рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб/рд╣реИрдХреНрд╕ рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рд╕реАрдХреНрд╡реЗрд▓рд╛рдЗрдЬ рдореЗрдВ рдУрдЖрд░рдПрдо рдореЙрдбрд▓ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

  • this рдЯрд╛рдЗрдк рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЗрд╕ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:
    ts abstract class Model { constructor(values: Partial<this.prototype>) }
  • рдкреНрд░рдХрд╛рд░ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд╡рд░реНрдЧ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░рдирд╛ рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╕реНрдерд┐рд░ рд╕рджрд╕реНрдп рд╕рд╛рдорд╛рдиреНрдп рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗ рд╣реИрдВ
  • рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдзрд┐ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рдХрд╛рд░ рдкрд╛рд╕ рдХрд░рдирд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕реНрдерд┐рд░ рдЧреБрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕реЗ:
    ts abstract class Model { static attributes: { [K in keyof this.prototype]: { type: DataType, field: string, unique: boolean, primaryKey: boolean, autoIncrement: boolean } }; }

рдЗрд╕ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП +1ред рдореЗрд░рд╛ рдУрдЖрд░рдПрдо рдмрд╣реБрдд рд╕рд╛рдл рд╣реЛрдЧрд╛ред

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рд╣рдо рдЬрд▓реНрдж рд╣реА рд╕реНрд╡рдЪреНрдЫ рд╕рдорд╛рдзрд╛рди рджреЗрдЦреЗрдВрдЧреЗ

рдЗрд╕ рдмреАрдЪ, рд╕рдорд╛рдзрд╛рди рдХреА рдкреЗрд╢рдХрд╢ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдХреЛ рдзрдиреНрдпрд╡рд╛рдж!

рдХреНтАНрдпрд╛ рд╣рдо рдЗрд╕ рдкрд░ рдФрд░ рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ рдХреНтАНрдпреЛрдВрдХрд┐ рдЕрдм рдХреЛрдИ рдЪрд░реНрдЪрд╛ рдирд╣реАрдВ рд╣реИ?

рдЖрдк рдЗрд╕реЗ рдХрд╣рд╛рдБ рд▓реЗ рдЬрд╛рдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ? рдпрд╣ рдЕрднреА рднреА рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдореЙрдбрд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рди рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдХрд╛рдо рдХреЛ рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИред

рдпрд╣ рдУрдЖрд░рдПрдо рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдЬрд░реВрд░реА рд╕реБрд╡рд┐рдзрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рддреАрди рд▓реЛрдХрдкреНрд░рд┐рдп рдУрдЖрд░рдПрдо рдорд╛рд▓рд┐рдХреЛрдВ рдиреЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ рд╣реИред

@pleerock @xealot Solutions рдКрдкрд░ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХрд┐рдП рдЧрдП рд╣реИрдВ:

export type StaticThis<T> = { new (): T };

export class Base {
    static create<T extends Base>(this: StaticThis<T>) {
        const that = new this();
        return that;
    }
    baseMethod() { }
}

export class Derived extends Base {
    derivedMethod() { }
}

// works
Base.create().baseMethod();
Derived.create().baseMethod();
// works too
Derived.create().derivedMethod();
// does not work (normal)
Base.create().derivedMethod();

рдореИрдВ рдЗрд╕рдХрд╛ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдЖрдзрд╛рд░ рд╡рд░реНрдЧреЛрдВ рдореЗрдВ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рдШреЛрд╖рдгрд╛рдПрдВ рдереЛрдбрд╝реА рднрд╛рд░реА рд╣реИрдВ рд▓реЗрдХрд┐рди рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдЕрдВрджрд░ this рдХреЗ рдкреНрд░рдХрд╛рд░ рдкрд░ рд╡рд┐рдХреГрддрд┐ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рднреБрдЧрддрд╛рди рдХрд░рдиреЗ рдХреА рдХреАрдордд рд╣реИред

@рдкреНрд▓реЗрд░реЙрдХ

рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдЗрди-рд╣рд╛рдЙрд╕ рдУрдЖрд░рдПрдо рд╣реИ рдЬреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ this: рдкреИрдЯрд░реНрди рдХрд╛ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рднрд╛рд╖рд╛ рдХреЛ рдЕрдзрд┐рднрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ рдЬрдм рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдпрд╣рд╛рдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдереЛрдбрд╝рд╛ рдЬрдЯрд┐рд▓ рд╣реИред рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ-рдорд╛рдорд▓рд╛ рдмрд╣реБрдд рд╕реАрдорд┐рдд рдЗрдореНрд╣реЛ рд╣реИ рдФрд░ рд╡рд┐рд╕рдВрдЧрддрд┐рдпреЛрдВ рдХреЛ рдкреЗрд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рд╢рд╛рдпрдж рдЗрд╕ рдкреНрд░рд╢реНрди рдФрд░ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдзрд╛рдЧрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

@bjouhier @ceymard рдореИрдВрдиреЗ рд╕рдордЭрд╛рдпрд╛ рдХрд┐ рдЗрд╕ рдереНрд░реЗрдб рдореЗрдВ рд╕рднреА рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб Sequelize рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ: https://github.com/Microsoft/TypeScript/issues/5863#issuecomment -269463313

рдФрд░ рдпрд╣ рдХреЗрд╡рд▓ рдУрдЖрд░рдПрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рднреА рд╣реИ: https://github.com/Microsoft/TypeScript/issues/5863#issuecomment -244550725

@felixfbecker рдиреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдФрд░ рдЗрд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ (рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ TS рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╣рд░ рдЙрдкрд╡рд░реНрдЧ рдореЗрдВ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░реЛрдВ рдХреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ)ред

@felixbecker рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдореИрдВ рдЗрд╕реЗ рдкреИрд░рд╛рдореАрдЯрд░ рд░рд╣рд┐рдд рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░реНрд╕ рд╕реЗ рдЪрд┐рдкрдХрд╛рдХрд░ рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рд╡рд┐рд╢реЗрд╖ рд╕реНрдЯреИрдЯрд┐рдХ рддрд░реАрдХреЗ рдкреНрд░рджрд╛рди рдХрд░рдХреЗ рд╣рд▓ рдХрд░рддрд╛ рд╣реВрдВ (рдХреНрд░рд┐рдПрдЯ, рдХреНрд▓реЛрди, ...) рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рдФрд░ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рдиред

@bjouhier рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реЛрдЧрд╛ рдХрд┐ рдЖрдкрдХреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЙрдбрд▓ рдЙрдкрд╡рд░реНрдЧ рдореЗрдВ рд╣рд░ рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рджреЗрдЦрд┐рдП Sequelize рдореЗрдВ рдХрд┐рддрдиреЗ рд╣реИрдВ: http://docs.sequelizejs.com/class/lib/model.js~Model.html

рдореЗрд░рд╛ рддрд░реНрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рд╣реИред рдЬрдмрдХрд┐ рдЖрдВрд╢рд┐рдХ рдФрд░ рдХреБрдЫ рд╣рдж рддрдХ рдЕрдирдкреЗрдХреНрд╖рд┐рдд рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рд╣реИрдВ рдФрд░ рд╣рдо рдЗрд╕ рдмрд╛рдд рдкрд░ рдмрд╣рд╕ рдФрд░ рдЕрд╕рд╣рдордд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╡реЗ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИрдВ рдпрд╛ рдирд╣реАрдВ, рд╣рдо рдЗрд╕ рдмрд╛рдд рд╕реЗ рд╕рд╣рдордд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ рдРрд╕рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬрд╣рд╛рдВ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЖрд╕рд╛рдиреА рд╕реЗ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдореЙрдбрд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдФрд░ рдореЗрд░реА рд╕рдордЭ рдпрд╣ рд╣реИ рдХрд┐ рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

@felixfbecker

рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реЛрдЧрд╛ рдХрд┐ рдЖрдкрдХреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЙрдбрд▓ рдЙрдкрд╡рд░реНрдЧ рдореЗрдВ рд╣рд░ рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдШреЛрд╖рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

рдХреНрдпреЛрдВ? рдРрд╕рд╛ рдореЗрд░рд╛ рдЕрдиреБрднрд╡ рдХрддрдИ рдирд╣реАрдВ рд╣реИред рдХреНрдпрд╛ рдЖрдк рдХреЛрдб рдирдореВрдиреЗ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

@bjouhier рдореИрдВрдиреЗ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рдЕрдкрдиреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдХреЛрдб рдирдореВрдиреЗ рдХреЗ рд╕рд╛рде рдЧрд╣рд░рд╛рдИ рд╕реЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рд╣реИ, рдПрдХ рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП https://github.com/Microsoft/TypeScript/issues/5863#issuecomment -222348054

рд▓реЗрдХрд┐рди рдКрдкрд░ рдореЗрд░рд╛ create рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ ред create рд╡рд┐рдзрд┐ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рд╣реИред рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдШреЛрд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рднреА рдЗрд╕реЗ рдЙрдкрд╡рд░реНрдЧ рдореЗрдВ рдареАрдХ рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдлрд┐рд░ Model рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реЛрдЧреА?

@felixfbecker рдЖрдкрдХрд╛ _рдПрдХ рдкреНрд░рд╛рд░рдВрдн_ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

export type StaticThis<T> = { new (): T };

abstract class Model {
    public static tableName: string;
    public static findById<T extends Model>(this: StaticThis<T>, id: number): T {
        const instance = new this();
        // details omitted
        return instance;        
    }
}

class User extends Model {
    public static tableName = 'users';
    public username: string;
}

const user = User.findById(1); 
console.log(user.username);

@bjouhier рдареАрдХ рд╣реИ, рддреЛ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ this: { new (): T } рдПрдиреЛрдЯреЗрд╢рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЯрд╛рдЗрдк рдЕрдиреБрдорд╛рди рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред рдЬреЛ рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрдХрд▓рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реИред
рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХреЗ рдкрд╛рд╕ this рдкреИрд░рд╛рдореАрдЯрд░ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╣рд╛рдВ, рдпрд╣ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдПрдХ рд╕реНрдерд┐рд░ create рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рдХрд░, рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдПрдкреАрдЖрдИ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдореИрдВ рдЗрд╕реЗ рд╕рдордЭрддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдореМрдЬреВрджрд╛ рдПрдкреАрдЖрдИ рдХреЛ рдПрдХ рдШреЛрд╖рдгрд╛ рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рдпрджрд┐ this рдХрд╛ рдЕрд░реНрде рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ { new (): T } рд╣реИ, рддреЛ this рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ this рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП new this() рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рд╣реЛрдЧреАред рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд▓рд┐рдП, this рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдХреНрд▓рд╛рд╕ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХрд╛ рдкреНрд░рдХрд╛рд░ред

рдореБрдЭреЗ рдореМрдЬреВрджрд╛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдЖрддреА рд╣реИред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЙрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк рдЕрднреА рднреА рдПрдХ рдордзреНрдпрд╡рд░реНрддреА рдЖрдзрд╛рд░ рд╡рд░реНрдЧ ( BaseModel extends Model ) рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдареАрдХ рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЧрдпрд╛ create рдлрд╝рдВрдХреНрд╢рди рд╣реЛ рдФрд░ BaseModel рд╕реЗ рдЕрдкрдиреЗ рд╕рднреА рдореЙрдбрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдпрджрд┐ рдЖрдк рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдХреЗ рд╕реНрдерд┐рд░ рдЧреБрдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЖрдк рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

public static findById<T extends Model>(this: (new () => T) & typeof Model, id: number): T {...}

рд▓реЗрдХрд┐рди рдЖрдкрдХреЗ рдкрд╛рд╕ рд╢рд╛рдпрдж рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд╡реИрдз рдмрд┐рдВрджреБ рд╣реИред рдореБрдЭреЗ рдПрдХ рдХрдард┐рди рдХрд╛рд░рдг рдирд╣реАрдВ рджрд┐рдЦ рд░рд╣рд╛ рд╣реИ рдХрд┐ рд╕рдВрдХрд▓рдХ рдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХреНрдпреЛрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:

constructor(values: Partial<this>) {}

рдореИрдВ @xealot рд╕реЗ рд╕рд╣рдордд рд╣реВрдВ рдХрд┐ рдпрд╣рд╛рдВ рджрд░реНрдж рд╣реИред рдХрд┐рддрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрддрд╛ рдЕрдЧрд░ рд╣рдо рд▓рд┐рдЦ рдкрд╛рддреЗ

static findById(id: number): instanceof this { ... }

рдХреЗ рдмрдЬрд╛рдП

static findById<T extends Model>(this: (new () => T), id: number): T { ... }

рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдЯрд╛рдЗрдкрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо ( instanceof ?) рдореЗрдВ рдПрдХ рдирдП рдСрдкрд░реЗрдЯрд░ рдХреА рдЬрд░реВрд░рдд рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЕрдорд╛рдиреНрдп рд╣реИ:

static findById(id: number): this { ... }

TS 2.4 рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдЗрди рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЛ рддреЛрдбрд╝рд╛:
https://travis-ci.org/types/sequelize/builds/247636686

@sandersn @felixfbecker рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рд╡реИрдз рдмрдЧ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореИрдВ рдЗрд╕реЗ рдиреНрдпреВрдирддрдо рдлреИрд╢рди рдореЗрдВ рдкреБрди: рдкреЗрд╢ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред рдХреЙрд▓рдмреИрдХ рдкреИрд░рд╛рдореАрдЯрд░ contravariant рд╣реИред

// Hooks
User.afterFind((users: User[], options: FindOptions) => {
  console.log('found');
});

рдХреЛрдИ рдореМрдХрд╛ рдпрд╣ рдХрд┐рд╕реА рдмрд┐рдВрджреБ рдкрд░ рддрдп рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛?

рдореИрдВ рдЖрдЬ рднреА рдЗрд╕рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ред рдореВрд▓ рд░реВрдк рд╕реЗ рдореИрдВ рдЗрд╕ рддрд░рд╣ рдПрдХ рд╕рд┐рдВрдЧрд▓рдЯрди рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛:

abstract class Singleton<T> {
  private static _instance?: T

  public static function getInstance (): T {
    return this._instance || (this._instance = new T())
  }
}

рдЙрдкрдпреЛрдЧ рдХреБрдЫ рдРрд╕рд╛ рд╣реЛрдЧрд╛:

class Foo extends Singleton<Foo> {
  bar () {
    console.log('baz!')
  }
}

Foo.getInstance().bar() // baz!

рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рд▓рдЧрднрдЧ 10 рд░реВрдкреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдКрдкрд░ рд╡рд░реНрдгрд┐рдд StaticThis рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рдХрдИ рдЕрдиреНрдп рдХреЗ рд╕рд╛рдеред рдЕрдВрдд рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рд╕рдВрд╕реНрдХрд░рдг рд╣реИ рдЬреЛ рд╕рдВрдХрд▓рд┐рдд рднреА рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдлрд┐рд░ getInstance() рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреЗрд╡рд▓ Object рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдореБрдЭреЗ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрди рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдХрдард┐рди рд╣реИред

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдп:

class Singleton {
    private static _instance?: Singleton;

    static getInstance<T extends Singleton>(this: { new(): T }) {
      const constr = this as any as typeof Singleton; // hack
      return (constr._instance || (constr._instance = new this())) as T;
    }
  }

  class Foo extends Singleton {
    foo () { console.log('foo!'); }
  }

  class Bar extends Singleton {
    bar () { console.log('bar!');}
  }

  Foo.getInstance().foo();
  Bar.getInstance().bar();

this as any as typeof Singleton рднрд╛рдЧ рдмрджрд╕реВрд░рдд рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдмреЗрд╡рдХреВрдл рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ _instance рдХреЛ рд╡реНрдпреБрддреНрдкрдиреНрди рд╡рд░реНрдЧ рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдкрд░ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЖрдо рддреМрд░ рдкрд░, рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдХреЛ рдЖрдкрдХреЗ рдврд╛рдВрдЪреЗ рдореЗрдВ рджрдлрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЗрд╕рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдереЛрдбрд╝рд╛ рдмрджрд╕реВрд░рдд рд╣реИ рддреЛ рдЗрд╕рд╕реЗ рдЬреНрдпрд╛рджрд╛ рдиреБрдХрд╕рд╛рди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рд╡реНрдпреБрддреНрдкрдиреНрди рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ рд╕реНрд╡рдЪреНрдЫ рдХреЛрдб рдХреНрдпрд╛ рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИред

рдореИрдВ 2.8 рдирд╛рдЗрдЯрд▓реАрдЬрд╝ рдореЗрдВ рдЙрдореНрдореАрдж рдХрд░ рд░рд╣рд╛ рдерд╛ рдХрд┐ рдореИрдВ рдРрд╕рд╛ рдХреБрдЫ рдХрд░ рд╕рдХреВрдВ:

static findById(id: number): InstanceType<this> { ... }

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдРрд╕реА рдХреЛрдИ рдХрд┐рд╕реНрдордд рдирд╣реАрдВ :(

@bjouhier рдХреЛрдб рдЙрджрд╛рд╣рд░рдг рдПрдХ рдЖрдХрд░реНрд╖рдг рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди IntelliSense рд╕реНрд╡рдд: рдкреВрд░реНрдг рддреЛрдбрд╝реЗрдВред

рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ 16.3.0 рдЬрд╛рд░реА рдХреА рдЧрдИ рдереА рдФрд░ рдирдИ getDerivedStateFromProps рд╡рд┐рдзрд┐ рдХреЛ рдареАрдХ рд╕реЗ рдЯрд╛рдЗрдк рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд▓рдЧрддрд╛ рд╣реИ, рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рд╡рд░реНрдЧ рдкреНрд░рдХрд╛рд░ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреА рд╣реИ:

(рд╕рд░рд▓реАрдХреГрдд рдЙрджрд╛рд╣рд░рдг)

class Component<P, S> {

    static getDerivedStateFromProps?<K extends keyof S>(nextProps: P, prevState: S): Pick<S, K> | null

    props: P
    state: S
}

рдХреНрдпрд╛ рдХреЛрдИ рдЙрдкрд╛рдп рд╣реИ? (рдореИрдВ "рдЯрд╛рдЗрдкрд┐рдВрдЧ рдкреА рдФрд░ рдПрд╕ рдХреЛ рдкреАрдкреА рдФрд░ рдПрд╕рдПрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рдЧрд┐рдирддрд╛ рдФрд░ рдЖрд╢рд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЗрди рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрд░рд┐рд╡рд╛рд░реЛрдВ рдХреЛ рдареАрдХ рд╕реЗ рдореЗрд▓ рдЦрд╛рдПрдВрдЧреЗ" рдПрдХ рдХреЗ рд░реВрдк рдореЗрдВ: рдкреА)

рдкреАрдЖрд░: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24577

@cncolder рдореИрдВрдиреЗ рдЗрдВрдЯреЗрд▓рд┐рдЬреЗрдВрд╕ рдХреЛ рднреА рддреЛрдбрд╝рддреЗ рд╣реБрдП рджреЗрдЦрд╛ рд╣реИред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ рдЗрд╕рдХреА рд╢реБрд░реБрдЖрдд рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ 2.7 рд╕реЗ рд╣реБрдИ рдереАред

рдПрдХ рдЪреАрдЬ рдЬреЛ рдореИрдВ рдпрд╣рд╛рдВ рдирд╣реАрдВ рджреЗрдЦрддрд╛, рд╕рд┐рдВрдЧрд▓рдЯрди рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ - рд╕рд┐рдВрдЧрд▓рдЯрди/рдорд▓реНрдЯреАрдЯрди рд╡рд░реНрдЧ рдХреЛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХрдиреНрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреИрдЯрд░реНрди рд╣реЛрдЧрд╛ - рдФрд░ рдЗрд╕реЗ рдмрдврд╝рд╛рдпрд╛ рдирд╣реАрдВ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдкреНрд░рдХрд╛рд░ { new(): T } рд╣реИ рдПрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ - this рдЯрд░реНрдо рдпрд╛ рдпрд╣рд╛рдВ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдЕрдиреНрдп рд╕рдорд╛рдзрд╛рди ( instanceof this , typeof this рдЖрджрд┐) рдХреЛ рдЙрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрдиреЗ рдХреЗ рд╕рд╛рде рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕рдВрднрд╡ рд╣реИ рдпрджрд┐ рд╕рд┐рдВрдЧрд▓рдЯрди рдиреЗ рдЗрд╕рдХреЗ рдирд┐рд░реНрдорд╛рдг рдЖрджрд┐ рдХрд╛ рдЕрдиреБрд░реЛрдз рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЯрд╛рдЗрдкрд┐рдВрдЧ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рд╣рд░рд╛ рджреЗрддрд╛ рд╣реИ - рдПрдХ рд░рдирдЯрд╛рдЗрдо рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП ...

class Singleton {

  private static _instance?: Singleton;

  public static getInstance<T extends Singleton> ( this: { new(): T } ): T {
    const ctor: typeof Singleton = this as any; // hack
    return (ctor._instance || (ctor._instance = new this())) as T;
  }

  protected constructor ( ) { return; } 
}

class A extends Singleton {
  protected constructor ( ) {
    super();
  }
}

A.getInstance() // fails because constructor is not public

рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдЖрдкрдХреЛ getInstance() рдХреЗ рд╕рд╛рде TS рдореЗрдВ рд╕рд┐рдВрдЧрд▓рдЯрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реЛрдЧреА, рдЖрдк рдХреЗрд╡рд▓ рдПрдХ рд╡рд╕реНрддреБ рдХреЛ рд╢рд╛рдмреНрджрд┐рдХ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╛ рдпрджрд┐ рдЖрдк рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрдХреНрд╖рд╛рдУрдВ (рдирд┐рдЬреА рд╕рджрд╕реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рд╕ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗрдВ, рди рдХрд┐ рдХреНрд▓рд╛рд╕, рдпрд╛ рдХреНрд▓рд╛рд╕ рдПрдХреНрд╕рдкреНрд░реЗрд╢рди ( export new class ... ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рдпрд╣ рдорд▓реНрдЯреАрдЯрди рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧреА рд╣реИ - рдФрд░ рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ рдореБрдЭреЗ рдПрдХ рдРрд╕рд╛ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛ рд╣реИ рдЬреЛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, ... рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЕрднреА рднреА рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд┐рдирд╛ рдмрд╣реБрдд рд╣реИрдХреА рдорд╣рд╕реВрд╕ рдХрд░ рд░рд╣рд╛ рд╣реИ .. рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ

this -> { new(): T } & typeof Multiton | Function

class Multiton {
  private static _instances?: { [key: string]: any };

  public static getInstance<T extends Multiton> (
    this: { new(): T } & typeof Multiton | Function, key: string
  ): T {
    const instances: { [key: string]: T } =
      (this as typeof Multiton)._instances ||
     ((this as typeof Multiton)._instances = { });

    return (instances[key] ||
      (instances[key] = new (this as typeof Multiton)() as T)
    );
  }

  protected constructor ( ) { return; }
}

class A extends Multiton {
  public getA ( ): void { return; }
}
A.getInstance("some-key").getA();
assert(A.getInstance("some-key") === A.getInstance("some-key"))
new A(); // type error, protected constructor

рдореЗрд░реЗ рдкрд╛рд╕ рдХреБрдВрдЬреА рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдХреЛрдб рднреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╕реГрдЬрди рдкрд░ рдмрд╛рд▓ рд╡рд░реНрдЧ рдореЗрдВ рдкрд╣реБрдВрдЪ рдпреЛрдЧреНрдп рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕реЗ рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП рд╣рдЯрд╛ рджрд┐рдпрд╛ рд╣реИ ...

рдирдорд╕реНрддреЗред рдореБрдЭреЗ рдРрд╕реА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХрдиреНрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ "рдпрд╣" рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рдЯрд┐рдкреНрдкрдгреА рдХреЗ рд╕рдорд╛рдиред

рдореИрдВ рдПрдХ рд╡рд░реНрдЧ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдБред рдХреНрд▓рд╛рд╕ рдореЗрдВ рд╣реА рдХрдИ рдЧреБрдг рд╣реЛрддреЗ рд╣реИрдВ рдЗрд╕рд▓рд┐рдП рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд▓рдЧреЗрдЧрд╛ рдпрджрд┐ рдЙрд╕ рдХреНрд▓рд╛рд╕ рдХреЗ рд╕рднреА рдЧреБрдгреЛрдВ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдореИрдВ рдПрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рдЧреБрдгреЛрдВ рдХреЛ рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

class Vehicle {
  // many properties here
  // ...

  constructor(value: Partial<Vehicle>) {
      Object.assign(this, value)
  }
}

let vehicle = new Vehicle({
  // <-- IntelliSense works here
})

рдлрд┐рд░, рдореИрдВ рдХрдХреНрд╖рд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

class Car extends Vehicle {
  // more properties here
  // ...
}

let car = new Car({
  // <-- I can't infer Car's properties here
})

рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдкрд░ рднреА this рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

class Vehicle {
  // ...
  constructor(value: Partial<this>) {
      // ...

рдЗрд╕рд▓рд┐рдП, IntelliSense рдЕрддрд┐рд░рд┐рдХреНрдд рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЗ рдмрд┐рдирд╛ рдЪрд╛рдЗрд▓реНрдб рдХреНрд▓рд╛рд╕ рдХреЗ рдЧреБрдгреЛрдВ рдХрд╛ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддрд╛ рд╣реИ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ред рдХрдХреНрд╖рд╛ рдХреЛ рдкреНрд░рд╛рд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдпрд╣ рдЕрдзрд┐рдХ рдкреНрд░рд╛рдХреГрддрд┐рдХ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред

let car = new Car({
  // <-- Car's properties will be able to be inferred if Partial<this> is allowed
})

рдЖрдкрдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд - рдмрд╣реБрдд рдзрдиреНрдпрд╡рд╛рджред

рдореБрдЭреЗ рдЦреБрд╢реА рд╣реИ рдХрд┐ рдореБрдЭреЗ рдпрд╣ рдзрд╛рдЧрд╛ рдорд┐рд▓рд╛ред рдореБрдЭреЗ рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рдЧрдВрднреАрд░ рдореБрджреНрджрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ 3.0 рддрдХ рд▓реЗ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдирд┐рд░рд╛рд╢ рдерд╛ред

рд╕рднреА рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдФрд░ рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдЦреЗрд▓реЗ рдЧрдП рд╡рд┐рднрд┐рдиреНрди рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реБрдП, рдореИрдВ рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдкрд╣реБрдВрдЪрд╛ рд╣реВрдВ рдХрд┐ рд╣рдо рдЬреЛ рднреА рддреНрд╡рд░рд┐рдд рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рд╡рд╣ рдмрд╕ рд╡рд┐рдлрд▓ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рд╣реИ рдФрд░ рдЬрдм рдХреЛрдИ рд╕рдорд╛рдзрд╛рди рд╣реЛрддрд╛ рд╣реИред рдФрд░ рддрдм рддрдХ, рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╣рд░ рдЬрдмрд░рджрд╕реНрддреА рдХреЛ рдкреВрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдзрд┐рдХ рдореИрдиреБрдЕрд▓ рдХрд╛рдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдФрд░ рдПрдХ рдмрд╛рд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдЙрдкрднреЛрдХреНрддрд╛рдУрдВ рд╕реЗ рдЖрдкрдХреА рдЕрдкрдиреА рдорд╛рдирд╕рд┐рдХрддрд╛ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЖрдкрдиреЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпреЛрдВ рдЪреБрдирд╛, рдпрджрд┐ рд╡реЗ рдЖрдкрдХреЗ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡реИрдирд┐рд▓рд╛ рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдореЗрдВ рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдХреА рддрд░рд╣, VSCode рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

рд╕рд╛рде рд╣реА, рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдЦреБрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдЬрдм рд╡рд╛рд╕реНрддрд╡рд┐рдХ рднрд╛рд╖рд╛ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рдЯрд╛рдЗрдк рдХреА рдЧрдИ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрд╕реА рдХрд╛рд░рдг рдХреЗ рдЦрд┐рд▓рд╛рдл рдЬрд╛рддреА рд╣реИред

рд╕рднреА рдХреЗ рд▓рд┐рдП рдореЗрд░реА рд╕рд┐рдлрд╛рд░рд┐рд╢ рд╣реИ рдХрд┐ рдпрд╣ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рд╕реНрдХреНрд╡реАрдЧрд▓реА рджреЛрд╖рдкреВрд░реНрдг рд╣реИрдВ рдФрд░ рдЬрдм рд╕рдВрднрд╡ рд╣реЛ рддреЛ //@ts-ignore because my code works as expected рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рдпрджрд┐ рдЖрдкрдХрд╛ рд▓рд┐рдВрдЯрд░ рдЙрдЪрд┐рдд рдорд╛рдирд╡ рдмреБрджреНрдзрд┐ рдХреЗ рдкреНрд░рддрд┐ рдкреНрд░рддрд┐рд░рдХреНрд╖рд┐рдд рд╣реИ, рддреЛ рдпрд╣ рд╕рдордп рд╣реИ рдХрд┐ рд╡рд╣ рдЕрдкрдиреА рдЬрдЧрд╣ рдЬрд╛рдирддрд╛ рд╣реЛред

рдЕрджреНрдпрддрди :
рдореИрдВ рд╢рд╛рдпрдж-рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдерд┐рд░ рдЕрдиреБрдорд╛рди рдХреЛ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕рдЦреНрддреА рд╕реЗ рдкрд░рд┐рд╡реЗрд╢реА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдЖрдЙрдЯ-рдСрдл-рдж-рд╡реЗ рд╣реЛрдирд╛ рд╣реИред рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реИ, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕рдВрд╡рд░реНрджреНрдзрди рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рди рдХреЗрд╡рд▓ рдпрд╣ рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рд╡рд┐рд░рд╛рд╕рдд рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧреАред

export class Sequence<T> {
  static from(...values) {
    // тАж returns Sequence<T>
  };
}

export class Peekable<T> extends Sequence<T> {
  // no augmentations needed in actual class body
}

/// AMBIENT /// Usually keep those at the bottom of my files

export declare namespace Peekable {
  export function from<T>(... values: T[]): Peekable<T>;
}

рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдореИрдВ рдЗрд╕ рдкреИрдЯрд░реНрди рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛, рди рд╣реА рдпрд╣ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рд╣рд░ рдкрд░рд┐рджреГрд╢реНрдп рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдЕрднреА рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЕрдкреЗрдХреНрд╖рд╛ рдХреЗ рдЕрдиреБрд░реВрдк рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдпреЗ рд╡рд┐рдХрд▓реНрдк рд╕рдВрдмрдВрдзрд┐рдд рдЕрд╣рд╕рд╛рд╕ рд╕реЗ рдЙрдкрдЬрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдмрд┐рдВрджреБ рддрдХ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рдЕрдкрдиреА lib рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдХреЗрд╡рд▓ рджреЛ рд╡рд░реНрдЧ рдШреЛрд╖рдгрд╛рдПрдБ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ!

рд╕реБрд░рдХреНрд╖рд┐рдд рд╕рд░рдгреА

/**
 * Represents an Automation SAFEARRAY
 */
declare class SafeArray<T = any> {
    private constructor();
    private SafeArray_typekey: SafeArray<T>;
}

рд╡рд░реНрдбреЗрдЯ

/**
 * Automation date (VT_DATE)
 */
declare class VarDate {
    private constructor();
    private VarDate_typekey: VarDate;
}

рдЖрдЬ рдХреБрдЫ рджреЗрд░ рдЪрд░реНрдЪрд╛ рд╣реБрдИред рдкреНрд░рдореБрдЦ рдмрд┐рдВрджреБ:

  • рдХреНрдпрд╛ this рдЙрджрд╛рд╣рд░рдг рдкрдХреНрд╖ рдпрд╛ рд╕реНрдерд┐рд░ рдкрдХреНрд╖ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ?

    • рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╕реНрдерд┐рд░ рдкрдХреНрд╖ред рдЙрджрд╛рд╣рд░рдг рдкрдХреНрд╖ рдХреЛ InstanceTypeOf рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрджрд░реНрднрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╡рд┐рдкрд░реАрдд рд╕рддреНрдп рдирд╣реАрдВ рд╣реИред рдпрд╣ рд╕рдорд░реВрдкрддрд╛ рднреА рдмрдирд╛рдП рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ $# this 2$#$ рдХрд╛ рд╢рд░реАрд░ рдореЗрдВ this рдХреЗ рд╕рдорд╛рди рдкреНрд░рдХрд╛рд░ рд╣реИред

  • рд╕реБрджреГрдврд╝рддрд╛ рдХреА рд╕рдорд╕реНрдпрд╛

    • рдЗрд╕ рдмрд╛рдд рдХреА рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдПрдХ рд╡реНрдпреБрддреНрдкрдиреНрди рд╡рд░реНрдЧ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реВрдЪреА рдХрд╛ рдЙрд╕рдХреЗ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реВрдЪреА рд╕реЗ рдХреЛрдИ рд╕рдВрдмрдВрдз рд╣реИ

    • рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ рдХрдХреНрд╖рд╛рдПрдВ рдЕрдХреНрд╕рд░ рд╕реНрдереИрддрд┐рдХ-рдкрдХреНрд╖ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЛ рддреЛрдбрд╝рддреА рд╣реИрдВ

    • рдЧреИрд░-рдирд┐рд░реНрдорд╛рдг-рдкрдХреНрд╖ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдпреЛрдЧреНрдпрддрд╛ рд▓рд╛рдЧреВ рдХреА рдЬрд╛рддреА рд╣реИ рдФрд░ рдпрд╣ рдЖрдорддреМрд░ рдкрд░ рд╡рд╣реА рд╣реИ рдЬреЛ рд▓реЛрдЧ рд╡реИрд╕реЗ рднреА рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ

    • рд╣рдо рдкрд╣рд▓реЗ рд╣реА static new this() рдХреЗ рдЧрд▓рдд рдЖрд╣реНрд╡рд╛рди рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ

    • рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рдХреЛрдИ рднреА рдмрд╛рд╣рд░ рд╕реЗ рд╕реНрдерд┐рд░ this рдХреЗ рдирд┐рд░реНрдорд╛рдг рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкрдХреНрд╖ рдХреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ?

рдореМрдЬреВрджрд╛ рдЙрдкрд╛рдп:

class Foo {
    static boo<T extends typeof Foo>(this: T): InstanceType<T> {
        return (new this()) as InstanceType<T>;
    }
}

class Bar extends Foo {
}

// b: Bar
let b = Bar.boo();

рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдпрд╣ рдХреЗрд╡рд▓ рддрднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм Bar рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╣рд╕реНрддрд╛рдХреНрд╖рд░ Foo рдХреЗ рд▓рд┐рдП рдареАрдХ рд╕реЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдпреЛрдЧреНрдп рд╣реЛ

@RyanCavanaugh рдореИрдВ рдПрдХ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рд╕рд╛рде рдЖрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЬрд╣рд╛рдВ this рдХрд╛ рдореВрд▓реНрдп рдЖрдкрдХреЗ рдЙрджрд╛рд╣рд░рдг static boo<T extends typeof Foo>(this: T): InstanceType<T> рд╕реЗ рдЖрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓рд╛ред рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдореИрдВ рдЬреЗрдирд░рд┐рдХ рдкрд░ рд╕рдм рдХреБрдЫ рдлрд┐рд░ рд╕реЗ рдкрдврд╝рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА - рдирд╣реАрдВред рдЕрдЧрд░ рдореИрдВ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП this рдХреЛ clazz рд╕реЗ рдмрджрд▓ рджреЗрддрд╛ рд╣реВрдВ, рддреЛ рдпрд╣ рдЕрдм рдФрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ рдФрд░ рдХрдВрдкрд╛рдЗрд▓рд░ "рдЕрдкреЗрдХреНрд╖рд┐рдд 1 рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рд╢рд┐рдХрд╛рдпрдд рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди 0 рдорд┐рд▓рд╛ред" рддреЛ рд╡рд╣рд╛рдБ рдХреБрдЫ рдЬрд╛рджреВ рдЪрд▓ рд░рд╣рд╛ рд╣реИред рдХреНрдпрд╛ рдЖрдк рд╕рдордЭрд╛рдПрдБрдЧреЗ? рдпрд╛ рдореБрдЭреЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдореЗрдВ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВ?

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
рд╕рд╛рде рд╣реА, рдпрд╣ extends typeof Foo рдФрд░ рдХреЗрд╡рд▓ extends Foo рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реИ?

@creynders this рдПрдХ рд╡рд┐рд╢реЗрд╖ рдирдХрд▓реА рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ рдЬрд┐рд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдк рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ ред

рдЬреЗрдиреЗрд░рд┐рдХ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдкрд░ InstanceType<T> рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рдореЗрд░рд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

const _data = Symbol('data');

class ModelBase<T> {
    [_data]: Readonly<T>;

    protected constructor(data: T) {
        this[_data] = Object.freeze(data);
    }


    static create<T, V extends typeof ModelBase>(this: V, data : T): InstanceType<V> {
        return new this(data);
    }
}

interface IUserData {
    id: number;
}

class User extends ModelBase<IUserData> {}

User.create({ id: 5 });

рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рд▓рд┐рдВрдХ

@mastermatt рдУрд╣ рд╡рд╛рд╣, рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрдврд╝рддреЗ рд╕рдордп рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдЙрдард╛рдпрд╛ ... рдзрдиреНрдпрд╡рд╛рдж

@RyanCavanaugh рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рдореИрдВ рдЕрдкрдиреЗ рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛, рд▓реЗрдХрд┐рди рдореЗрд░реЗ рдкрд╛рд╕ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐рдпрд╛рдВ рднреА рд╣реИрдВ рдЬреЛ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддреА рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдпрд╣ рдирд╣реАрдВ рд╕рдордЭ рд╕рдХрддрд╛ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдЙрджрд╛рд╣рд░рдг:

class Foo {
    static boo<T extends typeof Foo>(this: T): InstanceType<T> {
        return (new this()) as InstanceType<T>;
    }

    boo<T extends typeof Foo>(this: InstanceType<T>): InstanceType<T> {
      return (this.constructor as T).boo();
    }
}

class Bar extends Foo {
}

// b: Bar
let b = Bar.boo();
// c: Foo
let c = b.boo();

рдЕрдЧрд░ рдореБрдЭреЗ рдЗрд╕ рдЖрдЦрд┐рд░реА рдореБрджреНрджреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рдорд╛рдзрд╛рди рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ рддреЛ рдореИрдВ рдХреБрдЫ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдЖрдиреЗ рддрдХ рд╕реЗрдЯ рдХрд░ рджреВрдВрдЧрд╛ред

рдЙрд╕ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рднреА рдзреНрдпрд╛рди рджреЗрдВ, рдпрджрд┐ рдЙрдкрд╡рд░реНрдЧ рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ super рдкрд░ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рднреА рдкрд░реЗрд╢рд╛рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ ... рдЗрди рджреЛ рдореБрджреНрджреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдХрд╛рдордХрд╛рдЬ рдареАрдХ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╡реЗ рджреЛ рдореБрджреНрджреЗ рд╣рдорд╛рд░реЗ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЕрд╡рд░реБрджреНрдз рд╣реИрдВред

IIRC рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдереЛрдбрд╝рд╛ рдЭреБрдХрд╛рдП рдмрд┐рдирд╛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд╡реНрдпрдХреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХреЗ рд░реВрдк рдореЗрдВ ; this.constructor рдмрд┐рд▓реНрдХреБрд▓ рднреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдк рдХреНрдпрд╛ рд╕реЛрдЪрддреЗ рд╣реИрдВ рдпрд╛ рдРрд╕рд╛ рд╣реА рдХреБрдЫ рд╣реИред

рдЙрд╕ рд╕рдЯреАрдХ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореЗрд░реЗ рдкрд╛рд╕ boo() рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡рд┐рдзрд┐ this рд▓реМрдЯрд╛рдПрдЧреА рдФрд░ рдереЛрдбрд╝рд╛ рдЕрдВрджрд░ рдзреЛрдЦрд╛ рджреЗрдЧреА, рдЬрд┐рд╕рд╕реЗ рд╕рдВрдХрд▓рдХ рдХреЛ рдпрд╣ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рд╣реЛрдирд╛ рдкрдбрд╝реЗрдЧрд╛ рдХрд┐ рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдХреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдореЗрд░рд╛ рд╕рд╛рдорд╛рдиреНрдп рддрд░реНрдХ рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдПрдкреАрдЖрдИ рдмрд╛рдХреА рдХреЛрдб рдХреЗ рд▓рд┐рдП рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд╣реЛ, рднрд▓реЗ рд╣реА рдХрднреА-рдХрднреА рдЗрд╕рдХрд╛ рдорддрд▓рдм рдереЛрдбрд╝рд╛ рдзреЛрдЦрд╛ рджреЗрдирд╛ рд╣реЛред

рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдХреБрдЫ рдФрд░ рдордЬрдмреВрдд рд╣реИ, рддреЛ рдореБрдЭреЗ рдЕрдЪреНрдЫрд╛ рд▓рдЧреЗрдЧрд╛

class Foo {
  static boo<T extends typeof Foo>(this: T): InstanceType<T> {
      return (new this()) as InstanceType<T>;
  }

  boo(): this {
    // @ts-ignore : wow this is ugly 
    return (this.constructor).boo();
  }
}

class Bar extends Foo {
}

// b: Bar
let b = Bar.boo();
// c: Bar !
let c = b.boo();

рдЖрдк рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдорд╛рд░реНрдЧ рдкрд░ рднреА рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдРрд╕рд╛ рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ;

interface FooMaker<T> {
  new(...a: any[]): T
  boo(): T
}


class Foo {
  static boo<T extends typeof Foo>(this: T): InstanceType<T> {
      return (new this()) as InstanceType<T>;
  }

  boo(): this {
    return (this.constructor as FooMaker<this>).boo();
  }
}

class Bar extends Foo {
}

// b: Bar
let b = Bar.boo();
// c: Bar !
let c = b.boo();

рдпрд╣ рднреА рдзреЛрдЦрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж рдереЛрдбрд╝рд╛ рдФрд░ рдирд┐рдпрдВрддреНрд░рд┐рдд? рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВ рдХрд╣ рд╕рдХрддрд╛ред

рддреЛ рд╕реНрдерд┐рд░ "рдмреВ" рд╡рд┐рдзрд┐ рдореЗрдВ рдкрд╣рд▓рд╛, this рддрд░реНрдХ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ, рдирд┐рдпрдорд┐рдд рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ? рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реЛрдВ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд▓рд┐рдВрдХ?

class Foo {
    static boo<T extends typeof Foo>(this: T): InstanceType<T> {
        return (new this()) as InstanceType<T>;
    }
}

class Bar extends Foo {
}

// b: Bar
let b = Bar.boo();

рдореБрдЭреЗ рд╡рд╣реА (рдХрдо рд╕реЗ рдХрдо рд╕рдорд╛рди) рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИред
рдореИрдВ JSDoc (рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдирд╣реАрдВ) рдХреЗ рд╕рд╛рде рд╡реЗрдирд┐рд▓рд╛ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕ рдереНрд░реЗрдб рдореЗрдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдЬреЗрдирд░рд┐рдХ рдХреЗ рдЗрд░реНрдж-рдЧрд┐рд░реНрдж рдШреВрдордиреЗ рд╡рд╛рд▓реЗ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ/рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рд▓реЗрдХрд┐рди рд░реВрдЯ рд╕рдорд╛рди рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЦреЛрд▓рд╛ рд╣реИ: #28880

рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рд╕рдЪрдореБрдЪ 3 рд╕рд╛рд▓ рд╣реЛ рдЪреБрдХреЗ рд╣реИрдВред
рдХреНрдпрд╛ рдХрд┐рд╕реА рдХреЛ рдЙрдкрдпреБрдХреНрдд рдХрд╛рдордХрд╛рдЬ рдорд┐рд▓рд╛ рдЬреЛ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░ рд╕рдХреЗ?

рддреАрди рд╕рд╛рд▓

@RyanCavanaugh рдХрд╛ рдХрд╛рдо рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рд╕реНрдерд┐рд░ рдПрдХреНрд╕реЗрд╕рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?

class Factory<T> {
  get(): T { ... }
}

class Base {
  static factory<T extends Base>(this: Constructor<T>): Factory<T> {
    //
  }

  // what about a getter?
  static get factory<** no generics allowed for accessors **> ...
}

рддреАрди рд╕рд╛рд▓

рдареАрдХ рд╣реИ, рдЖрдк рддрд╛рд░реАрдЦреЛрдВ рдХреЛ рдШрдЯрд╛рдиреЗ рдореЗрдВ рдЖрдзреЗ рдХреБрд╢рд▓ рд╣реИрдВред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдЖрдк рдХреЛрдИ рд╕рдорд╛рдзрд╛рди рдкреЗрд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? ;)

@RyanCavanaugh рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬрдм рд╣рдо рдЬрдирд░реЗрдЯрд░ рдореЗрдВ this рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХрд░рддреЗ рд╣реИрдВ:

class C {
  constructor(f: (this: this) => void) {
  }
}
new C(function* () {
  this;
  yield;
});

рдЬрдм рд╣рдо рдЬрдирд░реЗрдЯрд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо this рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреАрд░ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рддреЛ рдЕрдм рд╣рдореЗрдВ рдЙрдкрд╡рд░реНрдЧреЛрдВ рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ this рдкреНрд░рдХрд╛рд░ рдШреЛрд╖рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдорд╛рдорд▓рд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

      class Component extends Coroutine<void> implements El {
        constructor() {
          super(function* (this: Component) {
            while (true) {
              yield;
            }
          }, { size: Infinity });
        }
        private readonly dom = Shadow.section({
          style: HTML.style(`ul { width: 100px; }`),
          content: HTML.ul([
            HTML.li(`item`)
          ] as const),
        });
        public readonly element = this.dom.element;
        public get children() {
          return this.dom.children.content.children;
        }
        public set children(children) {
          this.dom.children.content.children = children;
        }
      }

https://github.com/falsandtru/typed-dom/blob/v0.0.134/test/integration/package.ts#L469

рдпрджрд┐ рд╣рдо рдЗрд╕реЗ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддреЛ рд╣рдореЗрдВ рдЙрдкрд╡рд░реНрдЧреЛрдВ рдореЗрдВ this рдкреНрд░рдХрд╛рд░ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╕реБрдкрд░ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдЬреЗрдирд░реЗрдЯрд░ рдХреЛ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдкрд░ this рд╡реИрд▓реНрдпреВ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдореИрдВрдиреЗ рдХреЛрдб рдореЗрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рд╕реЗ рдкрд░рд╣реЗрдЬ рдХрд┐рдпрд╛ рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдЧрдВрджрд╛ рд╣реИрдХ рд╣реИред рддреЛ рдпрд╣ рдкреИрдЯрд░реНрди рдореВрд▓ рд░реВрдк рд╕реЗ рд╡рд░реНрдЧ-рдЖрдзрд╛рд░рд┐рдд рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдмреЗрдореЗрд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╕рдмрд╕реЗ рд╕рд╛рдл рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рд╕реЗ рдмрд╛рд▓ рд╡рд░реНрдЧ рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

class Base {
    static foo<T extends typeof Base>() {
        let ctr = Object.create(this.prototype as InstanceType<T>).constructor;
        // ...
    }
}

class C extends Base {
}

C.foo();

рд╣рд╛рд▓рд╛рдБрдХрд┐ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореБрдЭреЗ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЬрд┐рд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИ, рд╡рд╣ рдЗрд╕рдХреЗ рдХрд╛рд░рдг рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдореБрджреНрджреЗ рдХреА рдПрдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирдЬрд╝рд░ рдХреЗ рдмрд╛рдж, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╢рд╛рдпрдж рдРрд╕рд╛ рд╣реА рд╣реИред рдХреГрдкрдпрд╛ рд╕реБрдзрд╛рд░ рдХрд░реЗрдВ рдпрджрд┐ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИред

рддреЛ рдореЗрд░реЗ рдкрд╛рд╕ рд╡рд┐рд░рд╛рд╕рдд рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд 2 рд╡рд░реНрдЧ рд╣реИрдВред

export class Target {
  public static create<T extends Target = Target>(that: Partial<T>): T {
    const obj: T = Object.create(this.prototype);
    this.mapObject(obj, that);
    return obj;
  }
  public static mapObject<T extends Target = Target>(obj: T, that: Partial<T>) {
    // works with "strictNullChecks": false
    obj.prop1 = that.prop1;
    obj.prop2 = that.prop2;
  }

  public prop1!: string;
  constructor(public prop2: string) {}
}

export class SubTarget extends Target {
  public subProp!: string;
}

рдЗрд╕рдХреЗ рдмрд╛рдж, рдореИрдВ SubTarget рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ mapObject рд╡рд┐рдзрд┐ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВред

  public static mapObject(obj: SubTarget, that: Partial<SubTarget>) {
    super.mapObject(obj, that);
    obj.subProp = that.subProp;
  }

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореБрдЭреЗ рдЙрдореНрдореАрдж рдереА рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдореБрдЭреЗ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИред

Class static side 'typeof SubTarget' incorrectly extends base class static side 'typeof Target'.
  Types of property 'mapObject' are incompatible.
    Type '(obj: SubTarget, that: Partial<SubTarget>) => void' is not assignable to type '<T extends Target>(obj: T, that: Partial<T>) => void'.
      Types of parameters 'obj' and 'obj' are incompatible.
        Type 'T' is not assignable to type 'SubTarget'.
          Property 'subProp' is missing in type 'Target' but required in type 'SubTarget'.

рдХреНрдпрд╛ рдпрд╣ рддреНрд░реБрдЯрд┐ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдХрд╛рд░рдг рдЙрддреНрдкрдиреНрди рд╣реБрдИ рд╣реИ? рдЕрдиреНрдпрдерд╛, рдПрдХ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

рдЦреЗрд▓ рдХреЗ рдореИрджрд╛рди рд╕реЗ рд▓рд┐рдВрдХ

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд░реНрдЧ рдХреЗ рдирдП рдЙрджрд╛рд╣рд░рдг рд▓реМрдЯрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕реНрдереИрддрд┐рдХ рддрд░реАрдХреЛрдВ рдХреЛ рдПрдиреЛрдЯреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдпрд╣рд╛рдВ рдЖрдпрд╛ рдерд╛ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ @SMotaal ( new this() рдХреЗ рд╕рдВрдпреЛрдЬрди рдореЗрдВ) рджреНрд╡рд╛рд░рд╛ рд╕реБрдЭрд╛рдпрд╛ рдЧрдпрд╛ рд╕рдорд╛рдзрд╛рди рд╕рдмрд╕реЗ рд╕рд╛рдл рд╣реИ рдФрд░ рдореЗрд░реЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЬреНрдпрд╛рджрд╛ рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИред рдпрд╣ рд╡рд╛рдВрдЫрд┐рдд рдЗрд░рд╛рджреЗ рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдореБрдЭреЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЙрд▓ рдкрд░ рд╕рд╛рдорд╛рдиреНрдп рд╡рд┐рдзрд┐ рдкрд░ рдкреНрд░рдХрд╛рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдВрддрд┐рдо рдХреЛрдб рдореЗрдВ рдХреЛрдИ рдУрд╡рд░рд╣реЗрдб рдирд╣реАрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рдЧрдВрднреАрд░рддрд╛ рд╕реЗ, рдпрд╣ рдЕрднреА рддрдХ рдХреЛрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдХреИрд╕реЗ рдирд╣реАрдВ рд╣реИ? рдпрд╣ рдХрд╛рдлреА рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рджреГрд╢реНрдп рд╣реИред

@danielvy - рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ OOP рдФрд░ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЗ рдмреАрдЪ рдХрд╛ рдбрд┐рд╕реНрдХрдиреЗрдХреНрдЯ рдПрдХ рдмрдбрд╝рд╛ рдорд╛рдирд╕рд┐рдХ рдЕрдВрддрд░ рд╣реИ рдЬреЛ рд╕рднреА рдХреЛ рдЦреБрд╢ рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореВрд▓ рдзрд╛рд░рдгрд╛рдПрдВ рд╡рд░реНрдЧ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╡рд╛рдкрд╕ рдЖ рдЧрдИрдВ, рдФрд░ рдЗрд╕рд╕реЗ рдЯреВрдЯрдирд╛ рдХрдИ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдиреБрдХрд╕рд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рд░ рдХреЛрдИ "рдкреНрд░рд╛рдердорд┐рдХрддрд╛" рджреЗ рд░рд╣рд╛ рд╣реИ рдФрд░ рдпрд╣ рдареАрдХ рд╣реИ рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ " рдкреНрд░рдХрд╛рд░" рдореЗрд░реЗ рд╡рд┐рдЪрд╛рд░ рдореЗрдВред рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рд╕реЗ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рди рд╣реЛрдирд╛ рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЕрдЧрд░ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рд╣реИ, рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдПрдХ рдЯреЛрдХрд░реА рдореЗрдВ рд╕рднреА рдЕрдВрдбреЗ рд╣рдореЗрд╢рд╛ рд╕рднреА рдХреЗ рд▓рд┐рдП рдЦрд░рд╛рдм рд╣реЛрддреЗ рд╣реИрдВ - рдореИрдВ рдпрд╣рд╛рдВ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдФрд░ рдИрдорд╛рдирджрд╛рд░ рд╣реВрдВред

рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:

export class Base {
  static getEntitySchema<T extends typeof Base>(
    this: T,
  ): InstanceType<T> {
  }
}

export class Extension extends Base {
  static member: string = '';
  static getEntitySchema<T extends typeof Extension>(
    this: T,
  ): InstanceType<T> {
  }
}

Type 'typeof Base' is missing the following properties from type 'typeof Extension ': member.

рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдЗрд╕рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рд╡рд┐рд╕реНрддрд╛рд░ рдЖрдзрд╛рд░ рдмрдврд╝рд╛рддрд╛ рд╣реИ?

рдзреНрдпрд╛рди рджреЗрдВ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

export class Extension extends Base {
  static member: string = '';
  static getEntitySchema<T extends typeof Base>(
    this: T,
  ): InstanceType<T> {
  }
}

рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдк рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдЗрд╕рдХреЗ рдЕрдВрджрд░ рд╕рджрд╕реНрдпред

рддреЛ рдореИрдВ @ntucker рдкреЛрд╕реНрдЯ рд╕реЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗрд╡рд▓ рдПрдХ рд╕реНрддрд░ рдЧрд╣рд░рд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╡рд░реНрдЧ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рд╕реЗ рдмрд┐рд▓реНрдХреБрд▓ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддрд╛?

рдирдорд╕реНрдХрд╛рд░! рд╕рдВрд░рдХреНрд╖рд┐рдд рд░рдЪрдирд╛рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?

class A {
  static create<T extends A>(
    this: {new(): T}
  ) {
    return new this();
  }

  protected constructor() {}
}

class B extends A {} 

B.create(); // Error ts(2684)

рдпрджрд┐ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╣реИ - рдпрд╣ рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдпрд╣ рдПрдХ рддреНрд░реБрдЯрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ:

The 'this' context of type 'typeof B' is not assignable to method's 'this' of type '(new () => B) & typeof A'.
  Type 'typeof B' is not assignable to type 'new () => B'.
    Cannot assign a 'protected' constructor type to a 'public' constructor type.

рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди - http://tiny.cc/r74c9y

рдХреНрдпрд╛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЖрд╢рд╛ рд╣реИ? рдмрд╕ рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рдЗрд╕ рдЬрд░реВрд░рдд рдкрд░ рдареЛрдХрд░ рдЦрд╛рдИ :F

@ntuker Duuuuudee, рдЖрдкрдиреЗ рдХрд░ рджрд┐рдЦрд╛рдпрд╛ !!! рдореЗрд░реЗ рд▓рд┐рдП рдореБрдЦреНрдп рдЕрд╣рд╕рд╛рд╕ рдерд╛ рд╕реНрдереИрддрд┐рдХ рдирд┐рд░реНрдорд╛рдг рд╡рд┐рдзрд┐ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рдмрдирд╛рдирд╛, this рдкрд░рдо рдШреЛрд╖рд┐рдд рдХрд░рдирд╛, рдФрд░ рдлрд┐рд░ рдЕрдВрдд рдореЗрдВ InstanceType<U> рдХрд╛рд╕реНрдЯ рдХрд░рдирд╛ред

рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди

рдКрдкрд░ рд╕реЗ ^

class Base<T> {
  public static create<U extends typeof Base>(
    this: U
  ) {
    return new this() as InstanceType<U>
  }
}
class Derived extends Base<Derived> {}
const d: Derived = Derived.create() // works ЁЯШД 

рдпрд╣ рдореЗрд░реЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЯреАрдПрд╕ 3.5.1 рдХреЗ рд░реВрдк рдореЗрдВ рдпрд╣ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреАрдкреАрдПрд▓ рдХреЛ рднреА рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ (рд╕реНрдерд┐рд░ рдкреНрд░реЛрдк theAnswer рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рддреАрд╕рд░реЗ рд╕реНрддрд░ рдХреА рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рджреЗрдЦреЗрдВ)

рд╣реЙрдЯ рдЯреЗрдХ: рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдм рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдмрдВрдж рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?

@jonjaques рдмреАрдЯреАрдбрдмреНрд▓реНрдпреВ рдЖрдк рдХрднреА рднреА рдЯреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдЙрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд┐рдпрд╛ рд╣реИ рдЬреЛ рдУрд╡рд░рд░рд╛рдЗрдбрд┐рдВрдЧ рд╡рд┐рдзрд┐рдпрд╛рдВ рд╣реИрдВред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рд╕рдорд╛рдзрд╛рди рд▓рдЧрднрдЧ 4 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд╣реА рд╕реБрдЭрд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ ... рдФрд░ рдлрд┐рд░ рднреА рдпрд╣ рдРрд╕рд╛ рдХреБрдЫ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред

рдореИрдВрдиреЗ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рдЦреЛрд▓рд╛ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рдЕрдиреНрдп рдХрд╛рдордХрд╛рдЬ рдерд╛ рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЬрд╛рдирддрд╛ рд╣реЛ рдФрд░ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдЕрдЪреНрдЫрд╛ рд╕рд╛рд░рд╛рдВрд╢ рдерд╛ рдЬреЛ рдореИрдВ рдЕрдиреБрднрд╡ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ:

"рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рд╕рд╣рд┐рдд рд╡рд┐рдзрд┐ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЬреЗрдирд░рд┐рдХ, рд╡рд┐рд░реЛрдзрд╛рднрд╛рд╕реА рдкреНрд░рддреАрдд рд╣реЛрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдк рд╣рдореЗрд╢рд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕рд╣рд╕рдВрдпреЛрдЬрдХ (рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рджреНрд╡рд┐рднрд╛рдЬрд┐рдд) рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛рдПред"

рддреЛ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреБрдЫ рдРрд╕рд╛ рд╣реИ рдЬреЛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рд╣реА рдЯреВрдЯрд╛ рд╣реБрдЖ рд╣реИ рдФрд░ рдЗрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП ('рдпрд╣' рд╕рд╣рд╕рдВрдпреЛрдЬрдХ рдпрд╛ рджреНрд╡рд┐рдЪрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП)ред

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдЗрд╕ рдЯрд┐рдкреНрдкрдгреА рдХрд╛ рдПрдХ рдмреЗрд╣рддрд░ рддрд░реАрдХрд╛ рд╣реИред

рдореЗрд░реЗ рдкрд╛рд╕ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХреБрдЫ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП https://github.com/microsoft/TypeScript/issues/5863#issuecomment -437217433 рд╕реЗ рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд┐рдпрд╛

class Foo {
    static create<T extends typeof Foo>(this: T): InstanceType<T> {
        return (new this()) as InstanceType<T>;
    }
}

class Bar extends Foo { }

// typeof b is Bar.
const b = Bar.create()

рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рднреА рдЙрдкрдпреЛрдЧреА рд╣реИ рдЬреЛ рдЗрд╕ рд▓рдВрдмреЗ рдореБрджреНрджреЗ рдХреЛ рдмреНрд░рд╛рдЙрдЬрд╝ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИред

рдПрдХ рдЕрдиреНрдп рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдЧреИрд░ рд╡рд░реНрдЧреЛрдВ рдкрд░ рдХрд╕реНрдЯрдо рдкреНрд░рдХрд╛рд░ рдЧрд╛рд░реНрдб рд╕рджрд╕реНрдп рдХрд╛рд░реНрдп рд╣реИ:

type Baz = {
    type: "baz"
}
type Bar = {
     type: "bar"
}
type Foo = (Baz|Bar)&{
    isBar: () => this is Bar 
}

рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдореБрдЭреЗ рд▓рдЧрднрдЧ рд╡рд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдореБрдЭреЗ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдореЗрд░реЗ рдкрд╛рд╕ рдЧрд┐рдпрд░ рдореЗрдВ рдлреЗрдВрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд░рд┐рдВрдЪ рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд▓реНрдкрдирд┐рдХ рдЙрджрд╛рд╣рд░рдг рд▓реЗрдВ:

interface IAutomobileOptions {
  make: string
}

interface ITruckOptions extends IAutomobileOptions {
  bedLength: number
}

export class Automobile<O extends IAutomobileOptions> {
  constructor(public options: O) {}

  static create<T extends typeof Automobile, O extends IAutomobileOptions>(
    this: T,
    options: O
  ): InstanceType<T> {
    return new this(options) as InstanceType<T>
  }
}

export class Truck<O extends ITruckOptions> extends Automobile<O> {
  constructor(truckOptions: O) {
    super(truckOptions)
  }
}

const car = Automobile.create({ make: 'Audi' })
const truck = Truck.create({ make: 'Ford', bedLength: 7 }) // TS Error on Truck

рдпрд╣рд╛рдБ рддреНрд░реБрдЯрд┐ рд╣реИ:

The 'this' context of type 'typeof Truck' is not assignable to method's 'this' of type 'typeof Automobile'.
  Types of parameters 'truckOptions' and 'options' are incompatible.
    Type 'O' is not assignable to type 'ITruckOptions'.
      Property 'bedLength' is missing in type 'IAutomobileOptions' but required in type 'ITruckOptions'.ts(2684)

рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ create рд╡рд┐рдзрд┐ рдореЗрдВ Automobile рд╡рд░реНрдЧ рдореЗрдВ ITruckOptions рд╕реЗ O рдХрд╛ рдХреЛрдИ рд╕рдВрджрд░реНрдн рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рдХреЛрдИ рд╣реИ рдЙрд╕ рдореБрджреНрджреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдзрд╛рди?

рдЖрдо рддреМрд░ рдкрд░ рдХрдиреНрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╡рд░реНрдЧ 'рд╡рд┐рдХрд▓реНрдк рдмреЗрд╕ рдХреНрд▓рд╛рд╕' рд╡рд┐рдХрд▓реНрдк рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рд╣рдореЗрд╢рд╛ рдмреЗрд╕ рдХреНрд▓рд╛рд╕ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╡реЗ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд▓рд┐рдП рдкреИрд░рд╛рдореАрдЯрд░ рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ рдХрдХреНрд╖рд╛ред

рдореБрдЭреЗ рд╡рд┐рд░рд╛рд╕рдд рд╡рд░реНрдЧ рдХреЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЗрдирдкреБрдЯ рдФрд░ рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХреЗрд╡рд▓ рдУрд╡рд░рд░рд╛рдЗрдбрд┐рдВрдЧ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗрдирд╛ рдкрдбрд╝рд╛ рд╣реИ рдЬреЛ рдереЛрдбрд╝рд╛ рд╕рд╛ рд╕реБрдЧрдВрдзрд┐рдд рд▓рдЧрддрд╛ рд╣реИред

@ рдЬреИрдХ-рдмреИрд░реА рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

interface IAutomobileOptions {
  make: string
}

interface ITruckOptions extends IAutomobileOptions {
  bedLength: number
}

export class Automobile<O extends IAutomobileOptions> {
  constructor(public options: O) { }

  static create<T extends Automobile<O>, O extends IAutomobileOptions>(
    this: { new(options: O): T; },
    options: O
  ): T {
    return new this(options)
  }
}

export class Truck<O extends ITruckOptions> extends Automobile<O> {
  constructor(truckOptions: O) {
    super(truckOptions)
  }
}

const car = Automobile.create({ make: 'Audi' });
const truck = Truck.create({ make: 'Ford', bedLength: 7 });

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдЕрднреА рднреА рдЖрджрд░реНрд╢ рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд░рдЪрдирд╛рдХрд╛рд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╣реИрдВ рдЗрд╕рд▓рд┐рдП рдХреЗрд╡рд▓ new Automobile({ make: "Audi" }) рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред

@elderapo рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореБрдЭреЗ рд╡рд╣ рдорд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рдореБрдЭреЗ рдЪрд╛рд╣рд┐рдП - рдЙрджрд╛рд╣рд░рдг рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ рдХрд┐ _Generics_ рдХреА рдореЗрд░реА рд╕рдордЭ рдХреА рдХрдореА рдореБрдЭреЗ рдереЛрдбрд╝реА рд╕реА рдХрд╣рд╛рдВ рд╣реИред рдЗрд╕реЗ рдХреНрд▓реАрдпрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢реБрдХреНрд░рд┐рдпрд╛!

рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕рд╕реЗ рджреВрд╕рд░реЛрдВ рдХреЛ рдорджрдж рдорд┐рд▓реЗрдЧреА, рдЕрдЧрд░ рд╕реБрдзрд╛рд░ рдХреА рдХреЛрдИ рдЧреБрдВрдЬрд╛рдЗрд╢ рд╣реИ рддреЛ рдореБрдЭреЗ рдмрддрд╛рдПрдВред рдпрд╣ рд╕рд╣реА рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкрдврд╝рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдХ рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдЙрд╕ рдкреИрдЯрд░реНрди рдХреЗ рд╕рдмрд╕реЗ рдХрд░реАрдм рд╣реИ рдЬрд┐рд╕рдХреА рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдереАред

// Interface to ensure attributes that exist on all descendants
interface IBaseClassAttributes {
  foo: string
}

// Type to provide inferred instance of class
type ThisClass<
  Attributes extends IBaseClassAttributes,
  InstanceType extends BaseClass<Attributes>
> = {
  new (attributes: Attributes): InstanceType
}

// Constructor uses generic A to assign attributes on instances
class BaseClass<A extends IBaseClassAttributes = IBaseClassAttributes> {
  constructor(public attributes: A) {}

  // this returns an instance of type ThisClass
  public static create<A extends IBaseClassAttributes, T extends BaseClass<A>>(
    this: ThisClass<A, T>,
    attributes: A
  ): T {
    // Perform db creation actions here
    return new this(attributes)
  }

  // Note that read function is a place where typechecking could fail you if db
  //   return value does not match
  public static read<A extends IBaseClassAttributes>(id: string): A | null {
    // Perform db retrieval here assign to variable
    const dbReturnValue = {} as A | null
    return dbReturnValue
  }
}

interface IExtendingClassAttributes extends IBaseClassAttributes {
  bar: number
}

// Extend the BaseClass with the extending attributes interface
class ExtendingClass extends BaseClass<IExtendingClassAttributes> {}

// BaseClass
const bc: BaseClass = BaseClass.create({ foo: '' })
const bca: IBaseClassAttributes = BaseClass.read('a') as IBaseClassAttributes
console.log(bc.attributes.foo)
console.log(bca.foo)

// ExtendingClass
// Note that the create and read methods do not have to be overriden,
//  but typechecking still works as expected here
const ec: ExtendingClass = ExtendingClass.create({ foo: 'bar', bar: 0 })
const eca: IExtendingClassAttributes = ExtendingClass.read(
  'a'
) as IExtendingClassAttributes
console.log(ec.attributes.foo)
console.log(ec.attributes.bar)
console.log(eca.foo)
console.log(eca.bar)

рдЖрдк рдЗрд╕ рдкреИрдЯрд░реНрди рдХреЛ рд╢реЗрд╖ рд╕реАрдЖрд░рдпреВрдбреА рдХреНрд░рд┐рдпрд╛рдУрдВ рддрдХ рдЖрд╕рд╛рдиреА рд╕реЗ рдмрдврд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред

@ рдЬреИрдХ-рдмреИрд░реА рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдореИрдВ рдХрдХреНрд╖рд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП read рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реВрдВред рдореБрдЭреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЙрдореНрдореАрдж рдереА:

class BaseClass<A extends IBaseClassAttributes = IBaseClassAttributes> {

  public static read<A extends IBaseClassAttributes, T extends BaseClass<A>>(
    this: ThisClass<A, T>,
    id: string,
  ): T | null {
    // Perform db retrieval here assign to variable
    const dbReturnValue = {} as A | null
    if (dbReturnValue === null) {
      return null;
    }
    return this.create(dbReturnValue);
  }
}

рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рддреНрд░реБрдЯрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ Property 'create' does not exist on type 'ThisClass<A, T>'. рдХреНрдпрд╛ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдЗрд╕рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рд╣реЛрдЧрд╛?

@everhardt рдЪреВрдВрдХрд┐ create рд╡рд┐рдзрд┐ static рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ class рдХреЗ this рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред рдЙрд╕ рдиреЗ рдХрд╣рд╛ рдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрд░реЗ рд╕рд┐рд░ рдХреЗ рдКрдкрд░ рд╕реЗ рдПрдХ рдЕрдЪреНрдЫрд╛ рдХрд╛рдордХрд╛рдЬ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреИрд╕реЗ class рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬреЛ рдЕрднреА рднреА рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╛рдБрдЪ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред

рдореИрдВ рдЬреЛ рдирд┐рдХрдЯрддрдо рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рд╡рд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ, рдФрд░ рдореМрдЬреВрджрд╛ type рд╕реЗ BaseClass.create рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕рд┐рдВрдХ рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:

return (this.constructor as unknown as { create: (attributes: A) => T }).create(dbReturnValue)

рдореИрдВрдиреЗ _ рдирд╣реАрдВ _ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред

@ рдЬреИрдХ-рдмреИрд░реА рддреЛ рдЖрдкрдХреЛ this.constructor.create is not a function рдорд┐рд▓рддрд╛ рд╣реИред

рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ: рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ this рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдВрддрд┐рдо рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд╛рд░реНрд╕рд░ рдХреЗ рд▓рд┐рдП, this рд╡рд░реНрдЧ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдлрд╝рдВрдХреНрд╢рди рд╕реНрдерд┐рд░ рд╣реИред

рд╢рд╛рдпрдж рдЬреИрдХ-рдмреИрд░реА рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рд╕рдмрд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╡рд┐рд╕реНрддрд╛рд░ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рд▓рд┐рдВрдХ рдкрд░ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕реЗ рдХреИрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ред

рдирд┐рдЪреЛрдбрд╝:

  • рдкреНрд░рдХрд╛рд░ ThisClass рдХреЛ рд╕рднреА рд╕реНрдерд┐рд░ рдЧреБрдгреЛрдВ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдмреЗрд╕рдХреНрд▓рд╛рд╕ (рд╕реНрдерд┐рд░ рдФрд░ рдЙрджрд╛рд╣рд░рдг рджреЛрдиреЛрдВ) рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ 'рдЗрд╕' рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
  • рдЗрдВрд╕реНрдЯреЗрдВрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рд╕реНрдерд┐рд░ рд╕рдВрдкрддреНрддрд┐ рдпрд╛ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, (this.constructor as ThisClass<A, this>) . рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ

рдпрд╣ рджреЛрд╣рд░рд╛ рдХрд╛рдо рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рд╡рд░реНрдЧ рдФрд░ ThisClass рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕реНрдерд┐рд░ рддрд░реАрдХреЛрдВ рдФрд░ рдЧреБрдгреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░реЗ рд▓рд┐рдП рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рд▓рд┐рдВрдХ рддрдп рдХрд┐рдпрд╛

PHP рдиреЗ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрд╣реБрдд рдкрд╣рд▓реЗ рдареАрдХ рдХрд┐рдпрд╛ рдерд╛ред рд╕реНрд╡рдпрдВред рд╕реНрдерд┐рд░ред рдпрд╣ред

рдирдорд╕реНрдХрд╛рд░, рдпрд╣ 2020 рд╣реИ, рдЬрд┐рд╕рдореЗрдВ _this_ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдореИрдВ

class Animal { 
  static create() { 
    return new this()
  }
}
class Bunny extends Animal {}
const bugs = Bunny.create() // const bugs: Animal

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ bugs Bunny рдХрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реЛрдЧрд╛ред

рд╡рд░реНрддрдорд╛рди рдХрд╛рдордХрд╛рдЬ рдХреНрдпрд╛ рд╣реИ? рдореИрдВрдиреЗ рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ рд╕рдм рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ, рдХреБрдЫ рднреА рдареАрдХ рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИред

рдЕрджреНрдпрддрди : рдпрд╣ рдХрд╛рдо рдХрд┐рдпрд╛, this рддрд░реНрдХ рдкрд░рд┐рднрд╛рд╖рд╛ рд╕реЗ рдЪреВрдХ рдЧрдпрд╛ред

class Animal { 
  static create<T extends typeof Animal>(this: T): InstanceType<T> { 
    return (new this()) as InstanceType<T>
  }
}
class Bunny extends Animal {}
const bugs = Bunny.create() // const bugs: Bunny

рдЗрд╕рдХреЗ рд╕рд╛рде рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЧреЗрдЯрд░реНрд╕ рдФрд░ рд╕реЗрдЯрд░реНрд╕ рдореЗрдВ рдЯрд╛рдЗрдк рдкреИрд░рд╛рдореАрдЯрд░ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рднреА рд╡рд░реНрдмреЛрдЬрд╝ рд╣реИред

рдореИрдВ рдЗрд╕реА рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛ рд╕реЗ рдЬреВрдЭ рд░рд╣рд╛ рд╣реВрдВред "рдкреЙрд▓рд┐рдореЙрд░реНрдлрд┐рдХ рдЗрдирд░ рдХреНрд▓рд╛рд╕" рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдЬреЛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ рд╡рд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИ:

class BaseClass {
  static InnerClass = class BaseInnerClass {};

  static createInnerClass<T extends typeof BaseClass>(this: T) {
    return new this.InnerClass() as InstanceType<T['InnerClass']>;
  }
}

class SubClass extends BaseClass {
  static InnerClass = class SubInnerClass extends BaseClass.InnerClass {};
}

const baseInnerClass = BaseClass.createInnerClass(); // => BaseInnerClass

const subInnerClass = SubClass.createInnerClass(); // => SubInnerClass

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдареАрдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореЗрд░реА рд░рд╛рдп рдореЗрдВ createInnerClass() рдХреА рдЯрд╛рдЗрдкрд┐рдВрдЧ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╣реИ, рдФрд░ рдореЗрд░реЗ рдХреЛрдбрдмреЗрд╕ рдореЗрдВ рдореЗрд░реЗ рдкрд╛рд╕ рдмрд╣реБрдд рдХреБрдЫ рд╣реЛрдЧрд╛ред рдХреНрдпрд╛ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рд╣реИ?

рдЙрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╕реНрдерд┐рд░ рдЧреЗрдЯрд░реНрд╕ рдФрд░ рд╕реЗрдЯрд░реНрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рд╕реНрдерд┐рд░ рдЧреБрдгреЛрдВ рдХреЗ рд▓рд┐рдП self. рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ? рдореБрдЭреЗ 4 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдереА, рдФрд░ рдореИрдВ рдЙрд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рд╛рде рдЙрд╕реА рдзрд╛рдЧреЗ рдкрд░ рд╡рд╛рдкрд╕ рдЖ рд░рд╣рд╛ рд╣реВрдВред

@sudomaxime рдпрд╣ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ рдФрд░ рддрдм рддрдХ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдбрд┐рдЬрд╝рд╛рдЗрди рд▓рдХреНрд╖реНрдпреЛрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд рдЪрд▓рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ ECMAScript рдореВрд▓ рд░реВрдк рд╕реЗ self. рдХреЛ рдХрдХреНрд╖рд╛рдУрдВ рдореЗрдВ this.constructor. рдХреЗ рдЙрдкрдирд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ self рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЪрд░ рдирд╛рдо рд╣реИред

@ рдЕрдмреНрджреБрд▓реНрд▓рд╛-рдХрд╛рд╕рд┐рдо рдХрд╛ рд╕рдорд╛рдзрд╛рди рд╡рд░реНрдгрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд╡рд░реНрдЧреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реВрдВ:

class Animal<A> {
  public thing?: A;

  static create<T extends typeof Animal>(this: T): InstanceType<T> {
    return new this() as InstanceType<T>;
  }
}

type Foo = {};
class Bunny extends Animal<Foo> {}

const bunny = Bunny.create(); // typeof bunny is Animal<unknown>
bunny.thing;                  // unknown :(

   __     __
  /_/|   |\_\  
   |U|___|U|
   |       |
   | ,   , |
  (  = Y =  )
   |   `  |
  /|       |\
  \| |   | |/
 (_|_|___|_|_)
   '"'   '"'

рдореИрдВ рдЗрд╕ рдкрд░ рдХрд┐рд╕реА рднреА рд╡рд┐рдЪрд╛рд░ рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рд╕рд╛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рднрд╛рдЧреНрдп рдХреЗ рд╕рд╛рде рдЫреЗрдбрд╝рдЫрд╛рдбрд╝ рдХреА рд╣реИред

@stevehanson рдХреНрдпрд╛ рдпрд╣ рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛?

class Animal<A> {
  public thing?: A;

  static create<T>(this: new () => T): T {
    return new this() as T;
  }
}

type Foo = {asd: 123};
class Bunny extends Animal<Foo> {
    public hiya: string = "hi there"
}

const bunny = Bunny.create()


bunny.thing

const test = bunny.thing?.asd

const hiya = bunny.hiya

рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЦреЗрд▓ рдХреЗ рдореИрджрд╛рди рдкрд░ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ред

рдЗрд╕ рд▓рд┐рдВрдХ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд:
https://selleo.com/til/posts/gll9bsvjcj-generic-with-class-as-argument-and-returning-instance

рдФрд░ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ рдХрд┐ рдЯреА рд╡рд░реНрдЧ рд╣реА рд╣реИ ред рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рдЖрд╣, рдореБрдЭреЗ рдпрд╛рдж рдЖрдпрд╛, рдпрд╣ рдЯреА рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ рдХреНрдпреЛрдВрдХрд┐ рдореВрдХ this рдкреИрд░рд╛рдореАрдЯрд░ рд╣рдореЗрд╢рд╛ рдХрдХреНрд╖рд╛ рдХреЛ рд╣реА рдкрд╛рд╕ рдХрд░ рджреЗрдЧрд╛ред

@ рдЕрдмреНрджреБрд▓реНрд▓рд╛-рдХрд╛рд╕рд┐рдо рдпрд╣ рдХрд╛рдо рдХрд┐рдпрд╛! рд╡рд╛рд╣ рдзрдиреНрдпрд╡рд╛рдж! рдореЗрд░реЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП, рдореЗрд░рд╛ рдирд┐рд░реНрдорд╛рддрд╛ рдПрдХ рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдРрд╕рд╛ рджрд┐рдЦрддрд╛ рдерд╛, рдЕрдЧрд░ рдпрд╣ рдХрд┐рд╕реА рдФрд░ рдХреА рдорджрдж рдХрд░рддрд╛ рд╣реИ:

  static define<C, T, F = any, I = any>(
    this: new (generator: GeneratorFn<T, F, I>) => C,
    generator: GeneratorFn<T, F, I>,
  ): C {
    return new this(generator);
  }

рдпрд╣рд╛рдВ рдХреБрдЫ рд╕рдорд╛рдзрд╛рди рд╕реНрдерд┐рд░ рдЧреЗрдЯрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЗрд╕рдореЗрдВ рдХреЛрдИ рддрд░реНрдХ рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛:

рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдореИрдВ default рд╕реНрдерд┐рд░ рдЧреЗрдЯрд░ рдХреЛ рдореВрд▓ рд╡рд░реНрдЧ рдореЗрдВ рдХреИрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ?

class Letters {
  alpha: string = 'alpha'
  beta?: string
  gamma?: string
  static get default () {
    return new this()
  }
}

const x = Letters.default.alpha;

рдпрджрд┐ рд╣рдо рдХрднреА рд╡рд╛рдХреНрдп рд░рдЪрдирд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рддреЛ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдмрд╛рдд рд╣реЛ рд╕рдХрддреА рд╣реИред

рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд: рдореБрдЭреЗ @ abdullah-kasim рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдЕрдореВрд░реНрддрддрд╛ рдХреА рдПрдХ рдФрд░ рдкрд░рдд рдЬреЛрдбрд╝рдиреЗ рдореЗрдВ рдХрдард┐рдирд╛рдИ рд╣реЛ рд░рд╣реА рд╣реИред рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ, рдореИрдВ Animal рдХреЛ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдмрджрд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдФрд░ Bunny рдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕реНрдерд┐рд░ create() $ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдпрд╣рд╛рдБ рдПрдХ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ (рдмрдиреА рд╕рд╛рджреГрд╢реНрдп рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЗрдВ!) рдореИрдВ рдХреБрдЫ рдЕрд▓рдЧ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдПрдХ рд╕реНрдерд┐рд░ рдлрд╝реИрдХреНрдЯрд░реА рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИред рдореИрдВ рдпрд╣ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдПрдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкреНрд░рдХрд╛рд░ рдХреЛ рдХреЗрд╡рд▓ рдЕрдкрдиреЗ рд▓рд┐рдП рдПрдХ рдкрд╛рд░реНрд╕рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдЕрдиреНрдп рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдПред

(рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдХреЗ рдкреНрд░рдХрд╛рд░ рдмрд┐рд▓реНрдХреБрд▓ рд╕рд╣реА рдирд╣реАрдВ рд╣реИрдВ - рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдореИрдВ рдХреНрдпрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ)

interface ParseableDoc {
    parse<T>(this: new () => T, serialized:string): T|null;
}

interface Doc {
    getMetadata():string;
}

// EXPECT: no error!
const MarkdownDoc:ParseableDoc = class implements Doc {
    constructor(private meta:string){ };
    getMetadata():string { return this.meta; };

    static parse(serialized:string):typeof MarkdownDoc | null {
        // do something specific
        return null;
    }
}

// EXPECT: type error, since class defines no static parse()
const MissingParseDoc:ParseableDoc = class implements Doc {
    constructor(private meta:string){ };
    getMetadata():string { return this.meta; };
}

// EXPECT: type error, since parse() should return a MismatchedDoc
const MismatchDoc: ParseableDoc = class implements Doc {
    constructor(private meta:string){ };
    getMetadata():string { return this.meta; };

    static parse(serialized:string):typeof MismatchDoc | null {
        // do something specific
        return null;
    }
}

(рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ) рдореИрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛:

interface ParseableDoc {
    getMetadata():string;
    static parse<T extends ParseableDoc>(this: new () => T, serialized:string): T|null;
}

class MarkdownDoc implements ParseableDoc {
    getMetadata():string { return ""; }

    static parse(serialized:string):MarkdownDoc|null {
        // do something specific
        return null;
    }
}

рдХреЛрдИ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рднреА рдХрд╛рдордХрд╛рдЬ рд╕рдВрднрд╡ рд╣реИ рдпрд╛ рдирд╣реАрдВ?

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди

StackOverflow рдкрд░ рдПрдХ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛
рдЬреЗрдиреЗрд░рд┐рдХ рд▓реБрдХрдЕрдк рдЯреЗрдмрд▓ рдХреНрд▓рд╛рд╕ рдбрд┐рдЬрд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред

// Generic part
abstract class Table<T extends Model> {
    instances: Map<number, T> = new Map();
}
abstract class Model {
    constructor(
        public readonly id: number,
        public table: Table<this>  // Error
    ) { 
        table.instances.set(id, this);
    }
}

// Example: a table of Person objects
class Person extends Model {
    constructor(
        id: number,
        table: Table<this>,  // Error
        public name: string
    ) {
        super(id, table);
    }
}
class PersonTable extends Table<Person> {}

const personTable = new PersonTable();
const person = new Person(0, personTable, 'John Doe');

// Note: the idea of using `this` as generic type argument is to guarantee
// that other models cannot be added to a table of persons, e.g. this would fail:
//     class SomeModel extends Model { prop = 0; }
//     const someModel = new SomeModel(1, person.table);
//                                        ^^^^^^^^^^^^

@Think7 рдиреЗ 29 рдордИ 2016 рдХреЛ рдЯрд┐рдкреНрдкрдгреА рдХреА
рд╡рд┐рд╢реНрд╡рд╛рд╕ рдирд╣реАрдВ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрднреА рднреА рддрдп / рдЬреЛрдбрд╝рд╛ рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИ .....

рд╣рд╛ рд╣рд╛
2020 рдпрд╣рд╛рдБ рд╣реИ!

рдпрд╣ рд╣рд╛рд╕реНрдпрд╛рд╕реНрдкрдж рдФрд░ рдкрд╛рдЧрд▓ рд╣реИред рдпрд╣ 2020 рд╣реИред 4 рд╕рд╛рд▓ рдмрд╛рдж, рдЗрд╕реЗ рдареАрдХ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛?

рдХреНрдпреЛрдВ рди рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдП

class Model {
  static create(){
     return new static()
  }
  //or
  static create(): this {
     return new this()
  }
}

class User extends Model {
  //...
}

let user = new User.create() // type === User
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

bgrieder picture bgrieder  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Zlatkovsky picture Zlatkovsky  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

uber5001 picture uber5001  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

blendsdk picture blendsdk  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

kyasbal-1994 picture kyasbal-1994  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ