gpt4 book ai didi

TypeScript 意外交集

转载 作者:行者123 更新时间:2023-12-05 05:11:04 26 4
gpt4 key购买 nike

我有一个“模型”注册表,当我从注册表中选择一个模型并调用它的方法时,TypeScript 期望所有已注册模型的参数交集。

为简洁起见,我使用虚拟方法“getName”重现了这个错误。

export class Model<N extends string> {
public name: N;

constructor(name: N) {
this.name = name;
}

public getName = (options: { __type: N }) => options.__type;
}

export const Book = new Model("Book");
export const User = new Model("User");

export const modelRegistry = { Book, User };

export type ModelRegistry = typeof modelRegistry;

export const makeModel = <N extends keyof ModelRegistry>(name: N) => (
options: Parameters<ModelRegistry[N]["getName"]>[0],
) => {
const model = modelRegistry[name];
return model.getName(options); // <-- bug: TS expects this to be { __type: User } & { __type: Book }
};

enter image description here

Playground Link

最佳答案

这里的问题是编译器不知道如何解释泛型 ModelRegistry[N]["getName"]与类型相关 N当您尝试调用它时,反而加宽了 N到完整的联合类型keyof ModelRegistry .因此它看到model.getName作为不同参数类型的函数类型的联合。在 TypeScript 3.3 之前,这样的联合根本不可调用(参见 microsoft/TypeScript#7294 )。在 TypeScript 3.3 中添加了支持以允许此类函数成为 called with an intersection of the parameters for each function in the union .这比“不可调用”要好,但它仍然有很多不足之处,尤其是在您这里涉及相关联合类型的情况下(参见 microsoft/TypeScript#30581 )。

在这种情况下,解决它的最简单方法是接受你比编译器和 assert 更聪明的事实。您希望看到的类型。为了演示,我将只使用 as any使编译器静音:

export const makeModel = <N extends keyof ModelRegistry>(name: N) => (
options: Parameters<ModelRegistry[N]["getName"]>[0],
): ReturnType<ModelRegistry[N]["getName"]> => {
const model = modelRegistry[name];
return model.getName(options as any) as any; // I'm smarter than the compiler 🤓
};

这应该对你有用...你可以收紧 any如果您愿意,可以断言到更适用的类型。请注意,我已经手动注释了柯里化(Currying) makeModel 的返回类型调用 ReturnType<ModelRegistry[N]["getName"] ,因为编译器不太可能解决这个问题。

无论如何,希望对您有所帮助。祝你好运!

关于TypeScript 意外交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55933800/

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