gpt4 book ai didi

函数参数的 typescript 通用约束

转载 作者:行者123 更新时间:2023-12-02 01:08:09 25 4
gpt4 key购买 nike

编辑:
将接口(interface)中的“测试”固定为“约束”

我无法理解通用约束在 Typescript 中是如何工作的。我正在使用 React/Redux,您可以在其中找到与此类似的构造:

interface SomeConstraint { constraint: any }
type SomeType<T> = <A extends SomeConstraint>(item: T, action: A) => void;

如您所见,这是一个带有泛型参数和一些约束的函数定义。现在,当我想使用它时,我可以编写以下内容:
interface Test { constraint: string }
const some : SomeType<string> = (s: string, c: Test ) => {}

效果很好,但是,当我想扩展测试接口(interface)时(我们称之为TestWithData):
interface TestWithData  { constraint: string, payload: any }
const some : SomeType<string> = (s: string, c: TestWithData ) => {}

我得到一个编译时错误:

错误 TS2322:类型“(s:字符串,c:TestWithData)=> void”不可分配给类型“SomeType”。
参数“c”和“action”的类型不兼容。
类型“A”不可分配给类型“TestWithData”。
类型“SomeConstraint”不可分配给类型“TestWithData”。
“SomeConstraint”类型中缺少属性“test”。

我错过了什么?

已编辑

正如我所说,我在 redux 类型中发现了这个(类似的)构造。你可以找到这个定义(redux“3.7.2”):
export type Reducer<S> = <A extends Action>(state: S, action: A) => S;

现在,当您要定义 reducer 时,您需要提供状态和操作,我将跳过状态部分,因此,我可以将操作写入如下内容:
interface MyAction { type: "MY_ACTION" }

并且创建 reducer 很容易:
const reducer: Reducer<MyState> = (state: MyState, action: MyAction) => {...}

这将通过编译,但是如果我向 MyAction 添加其他数据,如下所示:
interface MyAction { 
type: "MY_ACTION";
payload: any
}

编译将因上述错误而失败。我怀疑它会通过。那么这个约束的目的是什么?告诉编译器我们期望完全相同的类型(结构上),仅此而已?我认为这是一个非常有限的用例,我希望类型推断会选择类型,检查它的结构兼容性并保留类型签名。像这样但不需要指定类型参数:
export type Reducer<S, A extends Action> = (state: S, action: A) => S;

现在,类型签名被保留,但我们需要在声明变量时指定实际参数类型(与我们为状态所做的相同):
const reducer: Reducer<MyState, MyAction> = (state: MyState, action: MyAction) => {...}

最佳答案

对于您给出的示例,我不认为泛型 + 约束是我定义类型的方式(这可能是我在名义类型系统中的方式,但不是在结构类型系统中)。

type SomeType<T> = <A extends SomeConstraint>(item: T, action: A) => void;

如果您说“该项目必须具有 constraint 属性,您可以使用更简单的方法来获得它:
type SomeType<T> = (item: T, action: SomeConstraint) => void;

结构类型负责其余的工作。

这是我的更新版本,因为之前的答案在 TypeScript 3.8.3 中停止工作。我已将约束设为通用,因为约束将与项目的类型相同。因为可以推断参数类型,所以我们不需要显式声明它们(即,我们不需要写 string 三次...像这样 const actualImplementation: SomeType<string> = (item: string, action: string): void => { } - 我们可以只写一次作为类型参数.
interface SomeConstraint<T> {
constraint: T
}

type SomeType<T> = (item: T, action: SomeConstraint<T>) => void;

const actualImplementation: SomeType<string> = (item, action): void => { }

const a: SomeConstraint<string> = { constraint: '' };

actualImplementation('', a);

上面例子的关键是实际的实现可以是你的 Test键入没有错误。

关于函数参数的 typescript 通用约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46559663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com