打字稿假定属性类型为 T | Properties["key"] 而不是 T

时间:2021-07-19 12:18:02

标签: typescript typescript-generics

假设我们有一个这样定义的类型:

type PropsBase<T> = {
    optionalProp?: T;
} 

type Props<T, TAdditionalProps extends object> = PropsBase<T> & TAdditionalProps

基本上我有一个通用的属性对象,然后子类可以在需要时添加更多属性。 然后我想这样使用它:

type State<T> = {
    value: T;
}

abstract class Base<T, TAdditional extends object = {}> {
    state: State<T>;
    constructor(props: Readonly<Props<T, TAdditional>>) {
        this.state = {
            value: props.optionalProp || this.fallbackValue() // ERROR!
        }
    }

    abstract fallbackValue(): T;
}

这会导致以下错误:

TS2322: Type 'T | Props<T, TAdditional>["optionalProp"]' is not assignable to type 'T'.
   'T' could be instantiated with an arbitrary type which could be unrelated to 
   'T | Props<T, TAdditional>["optionalProp"]'.

如果我使 optionalProp 不是可选的(删除 ?)那么它可以工作,如果我从构造函数中删除 Readonly 并且只使用 Props<T, TAdditional> 代替它也可以工作。

所以我的问题是:为什么会发生这种情况?有没有办法在这里仍然使用 Readonly 并具有可选属性?

附言我的 tsconfig.json 中有 strict: true。我知道,如果我将其设置为 false,它会起作用。

2 个答案:

答案 0 :(得分:2)

我认为从 || 切换到 ??解决您的问题。

Playground

type PropsBase<T> = {
    optionalProp?: T;
} 

type Props<T, TAdditionalProps extends object> = PropsBase<T> & TAdditionalProps

type State<T> = {
    value: T;
}

abstract class Base<T, TAdditional extends object = {}> {
    state: State<T>;
    constructor(props: Readonly<Props<T, TAdditional>>) {
        this.state = {
            value: props.optionalProp ?? this.fallbackValue()
        }
    }

    abstract fallbackValue(): T;
}

答案 1 :(得分:0)

是的,严格模式不太好用。但我使用它的原因是 bodystrictBindCallApply。所以我的答案是 – 按属性设置属性:

strictNullChecks