在TypeScript Generics中使用“extends”关键字

时间:2017-04-06 23:16:34

标签: generics typescript

我无法弄清楚为什么下面的代码会导致错误。在这个简单的示例中,正如预期的那样,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>'
    }
}

我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

请注意,这不是上述问题的精确解决方案,而只是一种解决方法。但是,评论时间太长了。

关于第二个错误,即&#34;类型的参数&#39; {on:boolean; }&#39;不能分配给&#39; Partial&#39;&#34;类型的参数,社区中围绕此主题进行了一些讨论,例如: https://github.com/Microsoft/TypeScript/issues/12793https://github.com/DefinitelyTyped/DefinitelyTyped/pull/13155,但我没有找到与您的方案完全匹配的内容。

出于某种原因,尽管事实Partial<State>,TS确实无法推断Partial<BaseState>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上的约束。

答案 1 :(得分:0)

为什么不仅仅删除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>'
    }
}