Кастинг в дженериках - Typescript - PullRequest
0 голосов
/ 07 июня 2018

У меня есть базовый класс:

class ClassA {
    public prop1: string;
}

У меня есть универсальный интерфейс:

interface IMyInterface<T extends ClassA> {
    objA: T;
}

И универсальный класс:

class MyClass<T extends ClassA> implements IMyInterface<T> {
    public objA: T;

    public myMethod () {
        this.objA.prop1 = "foo"; // This is ok

        if ("prop2" in this.objA) {
            this.objA.prop2 = "bar"; // This is not
        }
    }
}

Как я могупринудительно prop2 в objA тогда и только тогда, когда это свойство существует в objA?

Должен ли я использовать приведение как (this.objA as ClassA & {prop2: string}).prop2 = "bar"?

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

Вы можете использовать защиту типов, как описано здесь , внутри Type Guards and Differentiating Types сессии

Ваш код будет выглядеть примерно так:

class ClassA {
    public prop1: string;
}

interface IMyInterface<T extends ClassA> {
    objA: T;
}

interface IProp2 {
    prop2: string;
}

function hasProp2(obj: ClassA | IProp2): obj is IProp2 {
    return (<IProp2>obj).prop2 !== undefined;
}

class MyClass<T extends ClassA> implements IMyInterface<T> {
    public objA: T;

    public myMethod () {
        this.objA.prop1 = "foo"; // This is ok

        if (hasProp2(this.objA)){
            this.objA.prop2 = "bar"; // Now this is ok
        }
    }
}
0 голосов
/ 07 июня 2018

Это, кажется, текущее ограничение Typescript.Я нашел эту проблему , описывающую этот конкретный случай.

Обходной путь такой же, как вы уже упоминали.Вам придется привести this.objA к другому типу, который позволяет установить поле prop2.Итак:

(this.objA as ClassA & {prop2: string}).prop2 = "bar"

// Or to trade some safety for brevity:
(this.objA as any).prop2 = "bar"

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

function inOperator<K extends string, T>(k: K, o: T): o is T & Record<K, any> {
    return k in o;
}

Затем, используя это вместо оператора in:

if (inOperator("prop2", this.objA)) {
    this.objA.prop2 = "bar"; // No error now
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...