Почему TypeScript жалуется на мою реализацию абстрактного члена класса? - PullRequest
0 голосов
/ 12 февраля 2019

Ниже приведен мой пользовательский тип:

type KeyMap<T> = { [K in keyof T]: keyof Pick<T, K> }

Далее следует простой интерфейс для использования с пользовательским типом:

interface MyInterface {
    a: string;
    b: string;
}

Когда переменная моего типа определена вне класса, TypeScript счастлив:

const member: KeyMap<MyInterface> = {
    a: 'a',
    b: 'b'
}

Но когда я определяю абстрактный класс с абстрактным членом типа KeyMap и пытаюсь реализовать его, он не работает.Например:

abstract class BaseClass<T> {
    protected abstract member: KeyMap<T>
    protected abstract method: () => void;
}

class DerivedClass extends BaseClass<MyInterface> {
    // TypeScript reports that property 'a' is not compatible with '"a"'
    protected member = { 
        a: 'a', 
        b: 'b'
    };

    protected method = () => console.log('');
}

Определение члена непосредственно в абстрактном или производном классе, похоже, работает.Например:

abstract class BaseClass {
    public member: KeyMap<MyInterface> = {
        a: 'a', 
        b: 'b'
    }
    protected abstract method: () => void;
}

class DerivedClass extends BaseClass {
    public derivedMember: KeyMap<MyInterface> = {
        a: 'a', 
        b: 'b'
    }

    protected method = () => console.log('');
}

Как и при изменении элемента на другой тип:

abstract class BaseClass<T> {
    protected abstract member: { c: string, d: string };
    protected abstract method: () => void;
}

class DerivedClass extends BaseClass<MyInterface> {
    protected member = { 
        c: 'c', 
        d: 'd'
    };

    protected method = () => console.log('');
}

Почему TypeScript сообщает о реализации member в производном классе как об ошибке, когда онработает вне класса и когда он не помечен как абстрактный?

TypeScript Playground Link

1 Ответ

0 голосов
/ 12 февраля 2019

Члены класса являются типами независимо от того, что находится в базовом классе, и только после этого производный класс проверяется на совместимость с базовым классом.Поскольку член набирается на основе значения инициализации, машинописный текст не будет использовать литеральные типы для типов свойств (есть только определенные места, в которых TS не будет расширять литеральный тип, и это не один из них)

Лучшее решениевы можете использовать явную аннотацию типа для участника, как вы уже сказали, что пытались ответить на вопрос:

class DerivedClass extends BaseClass<MyInterface> {
    protected member: KeyMap<MyInterface> = { 
        a: 'a', 
        b: 'b'
    };

    protected method = () => console.log('');
}
...