Объявите дополнительный член к методу класса - PullRequest
0 голосов
/ 06 ноября 2018

Я украсил метод декоратором машинописи, добавив в метод член:

export class MyClass {
    @AddMyMember()
    public myMethod(param1:string) {
        // ...
    }
}

Чтобы я мог использовать его следующим образом:

const myClassInstance = new MyClass();
myClassInstance.myMethod.myMember(); // error of course here, as myMember has not been declared yet...

Но я не могу найти способ эффективно объявить myMember:

export declare interface MyClass {
// Something great here maybe?....
}

1 Ответ

0 голосов
/ 09 ноября 2018

Проблема слияния

Невозможно объявить члена класса с другим типом, объединение объявлений может только добавлять членов, но не изменять типы существующих членов.

Что-то, что мы можем сделать, это использовать тип пересечения. Если два члена типа пересечения имеют одно и то же имя и разные типы, то член пересечения будет пересечением двух исходных типов.

class _MyClass {
    public constructor (t: string) {

    }
    public myMethod(param1:string) {
    }

    static staticF(){}
}

type ReplaceInstanceType<T extends new(...a: any[])=> any, TNew> = {
    new (... a: (T extends new (...p: infer P) => unknown ? P: [])) : TNew
} & Pick<T, keyof T>

export type MyClass = _MyClass & {
    myMethod: {
        myMember(): void
    }
}


export const MyClass: ReplaceInstanceType<typeof _MyClass, MyClass> = _MyClass as any;

let a = new MyClass("") // can new up
a.myMethod("") // can call myMethod
a.myMethod.myMember(); // can call  myMember
MyClass.staticF

Задача декоратора

Вторая часть вашей проблемы заключается в том, что декоратор не может изменить тип члена, к которому он применяется (это специально). Вместо этого вы можете использовать HOC для создания класса и передать список имен членов (проверка компиляции выполняется с помощью keyof) для добавления дополнительных членов:

type ReplaceInstanceType<T extends new(...a: any[])=> any, TNew> = {
    new (... a: (T extends new (...p: infer P) => unknown ? P: [])) : TNew
} & Pick<T, keyof T>

function addMemebers<T extends new(...a: any[])=> any, K extends keyof InstanceType<T>>(members: K[], cls: T) : ReplaceInstanceType<T, InstanceType<T> & Record<K, {myMember(): void}>>{
    return null as any; // replace with implementation
}
export const MyClass = addMemebers(["myMethod"], class {
    public constructor (t: string) {

    }
    public myMethod(param1:string) {
    }

    static staticF(){}
})


let a = new MyClass("") // can new up
a.myMethod("") // can call myMethod
a.myMethod.myMember(); // can call  myMember
MyClass.staticF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...