请考虑以下内容,
interface ITemplateA {
name: string;
}
const templateA = ({ name }: ITemplateA) => `Hello, I am ${name}`
interface ITemplateB {
age: number;
}
const templateB = ({ age }: ITemplateB) => `I am, ${age} years old`;
const templates = {
templateA,
templateB
}
interface IGenerateText {
template: keyof typeof templates;
params: any;
}
const generateText = ({ template, params }: IGenerateText) => templates[template](params);
我如何使用params: any
重构部件,以便typescript将获得以下内容:
generateText({ template: 'templateA', params: { name: 'michael' } }); // no error
generateText({ template: 'templateA', params: { age: 5 } }); // error
generateText({ template: 'templateB', params: { age: 5 } }); // no error
2条答案
按热度按时间yvgpqqbh1#
这似乎起到了作用。我想你也可以用一些聪明的方法去掉函数内部的
as any
。1l5u6lss2#
在外部(即调用函数时),有一个mapped type(就像您的例子中的
typeof templates
,templates
是一个Map/字典)和一个选择Map类型的键的推断泛型类型参数就足够了,以表达一些函数参数之间的相关性,就像@ARX的回答中所做的那样。但是在内部(即在函数体中),这种Map类型是不够的:TypeScript静态分析无法知道只使用了一个键类型(它仍然可以是键的并集),因此它只能保留所有类型的并集。
告诉TS只有一个键值存在的唯一方法是使用一些type narrowing。要让TS缩小相关参数的类型,它们必须是有区别的联合体的一部分。不幸的是,在您的情况下,这可能会导致一些重复的代码,目前无法避免以保持完全安全:
Playground链接
在您的例子中,函数内部的作用是显而易见的,我们可以接受类型Assert以避免重复的代码。