描述咖喱状态处理器的类型与反应,打字稿

问题描述 投票:3回答:2

我试图描述它处理更改事件,以反映状态值的函数的类型。

所需的实现将如下所示:

handleChange: ChangeHandler<State> = field => value =>
    this.setState({ [field]: value });

由于状态:

interface State {
  title: string;
  description: string | null;
}

人们可以此功能传递到组件为:

<TextComponent onChange={this.handleChange('title')} />

要解决这个问题我最好的尝试是创建以下类型:

type ChangeHandler<S> = <K extends keyof S, V extends S[K]>(key: K) => (value: V) => void;

然而,这似乎工作只有在国家的所有属性都是可选的。我不能设法得到这个既可选和非可选性的工作状态。

编译器错误:

[TS]类型{的”参数[X:字符串]:V; }“不是分配给参数类型的”国| ((prevState:只读,道具:只读)=>国家|接| NULL)|匹克<...> |空值'。 类型“{[X:字符串]:V; }”缺少从类型以下属性‘挑选’:标题,描述[2345]

reactjs typescript generics type-inference
2个回答
2
投票

根本原因

这是通过打字稿,其中包括文字的工会计算属性名被加宽一个known issue引起的。

handleChangefield的类型是从'title' | 'description'加宽到string,这会导致this.setState失败由于this.setState的方式分型中定义。

下面是setState的简单定义:

function setState<K extends keyof State>(s: Pick<State, K>): void {
    console.log(s);
}

当应用该定义handleChange,所述K以上变得'title' | 'description's参数变为Pick<State, 'title' | 'description'>,其基本上等同于State接口。

因此,考虑到我们的field已经扩大到stringthis.setState在这方面接受State,我们会给你所看到的,因为我们有以下类型的主叫this.setState错误:

{ [x: string]: V }

这是不能分配给State,因为它缺少所需的参数titledescription

我们这里最好的办法是使用类型断言沉默的误差,同时保持类型检查。更新后的定义如下:

let handleChange: ChangeHandler<State> = field => value =>
    setState({ [field]: value } as unknown as State);

let x = handleChange('title');

x('test'); // OK

x(50); // Error: should be string

this playground link含有上面的代码。


discussion对替代解决方案/方法上DefinitelyTyped这一具体问题。


0
投票

就不能定义为V extends S[K]你可以直接内联这个声明如下:

type ChangeHandler<S> = <K extends keyof S>(key: K) => (value: S[K]) => void;
© www.soinside.com 2019 - 2024. All rights reserved.