【问题标题】:Using "extends" keyword with TypeScript Generics在 TypeScript 泛型中使用“扩展”关键字
【发布时间】:2020-07-27 03:54:25
【问题描述】:

我不明白为什么下面的代码会导致错误。在这个简单的示例中,Component 类正如预期的那样没有问题。但是,明确定义State 扩展自BaseState 的通用实现似乎没有通过BaseState 提供的输入信息发送,从而导致错误。

interface BaseState {
    on: boolean;
    color: string;
};

class Component {
    state: BaseState;

    constructor(state: BaseState) {
        this.state = state;
    }

    setState(partialState: Partial<BaseState>) {
        this.state = { ...this.state, ...partialState };  // no error
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 });  // no error
    }
}

class GenericComponent<State extends BaseState> {
    state: State;

    constructor(state: State) {
        this.state = state;
    }

    setState(partialState: Partial<State>) {
        this.state = { ...this.state, ...partialState };  // error: Spread types may only be created from object types.
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 });  // error: Argument of type '{ on: boolean; }' is not assignable to parameter of type 'Partial<State>'
    }
}

我在这里错过了什么?

【问题讨论】:

标签: generics typescript


【解决方案1】:

请注意,这不是上述问题的确切解决方案,而只是一种解决方法。但是,它太长了,无法放入评论中。

关于第二个错误,即“Argument of type '{ on: boolean; }' is not assignable to parameter of type 'Partial'”,社区中已经围绕这个话题进行了一些讨论,例如https://github.com/Microsoft/TypeScript/issues/12793https://github.com/DefinitelyTyped/DefinitelyTyped/pull/13155,尽管我找不到与您的场景完全匹配的任何内容。

由于某种原因,TS 确实无法推断 Partial&lt;State&gt;Partial&lt;BaseState&gt; 的可分配性,尽管事实上 State extends BaseState

例如,下面这段代码会导致错误。

class SampleClass<State extends BaseState> {
    baseState: Partial<BaseState>;

    method(state: Partial<State>): void {
        this.baseState = state; // Type 'Partial<State>' is not assignable to type 'Partial<BaseState>'.
    }
}

这对我来说似乎很奇怪,我建议向 TypeScript 社区提交一个建议以供考虑。至少他们可以解释这是否例外以及原因。

在您上面给出的特定情况下,我建议通过以下方式显式转换部分的类型。

class GenericComponent<State extends BaseState> {
    state: State;

    constructor(state: State) {
        this.state = state;
    }

    setState(partialState: Partial<State>) {
        //  Some logic here
    }

    onInput({ value }: { value: number }) {
        this.setState({ on: value > 0 } as State); 
    }
}

据我所知,这段代码保持类型安全,并遵守State 的约束。

【讨论】:

    【解决方案2】:

    为什么不直接删除 extends 关键字?

    class GenericComponent {
        state: BaseState;
    
        constructor(state: BaseState) {
            this.state = state;
        }
    
        setState(partialState: Partial<BaseState>) {
            this.state = { ...this.state, ...partialState };  // error: Spread types may only be created from object types.
        }
    
        onInput({ value }: { value: number }) {
            this.setState({ on: value > 0 });  // error: Argument of type '{ on: boolean; }' is not assignable to parameter of type 'Partial<State>'
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-30
      • 2018-04-09
      • 2021-02-11
      • 1970-01-01
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多