我在将函数的预期参数动态Map到父 Package 器中选定的函数时遇到问题。我已经设法正确Map了所有 * 可以 * 调用的方法,但Typescript在我传递的参数处抛出错误。
这是我的想法:
type TGenerateSetA = { city: number; address: number; }
const setASelects = {
city: ({ appendComma }: { appendComma: boolean }) => `city${appendComma ? ',' : ''}`,
address: ({ appendComma }: { appendComma: boolean }) => `address${appendComma ? ',' : ''}`,
};
type TGenerateSetB = { user: number; role: number; }
const setBSelects = {
user: ({ appendComma }: { appendComma: boolean }) => `user${appendComma ? ',' : ''}`,
role: ({ appendComma }: { appendComma: boolean }) => `role${appendComma ? ',' : ''}`,
};
type TSetObject = Record<string, ({ appendComma }: { appendComma: boolean }) => string>;
interface ISetMapping {
SET_A: TSetObject
SET_B: TSetObject
}
const SELECTS: ISetMapping = {
SET_A: setASelects,
SET_B: setBSelects,
}
type TGenerateCommonResult = {
selectFrom: keyof ISetMapping;
} & TGenerateSetA
const generateCommonResult = ({ selectFrom, ...args }: TGenerateCommonResult) => {
const result: string[] = [];
const totalEnabledSelects = Object.values(args).reduce((acc, shouldSelect) => acc + shouldSelect, 0);
let selectsAdded = 0;
Object.entries(args).forEach(([select, shouldSelect], index, self) => {
if (shouldSelect) {
result.push(SELECTS[selectFrom][select]({appendComma: selectsAdded + 1 !== totalEnabledSelects}));
}
selectsAdded++;
});
return result.join(' ');
}
console.log(generateCommonResult({ selectFrom: 'SET_A', city: 1, address: 0 })); // no error expected
console.log(generateCommonResult({ selectFrom: 'SET_B', user: 1, city: 0 })); // error expected
console.log(generateCommonResult({ selectFrom: 'SET_B', user: 1, role: 0 })); // no error expected
我怎样才能让它工作?
Playground链接
1条答案
按热度按时间yqlxgs2m1#
看起来你想让
TGenerateCommonResult
成为一个有区别的联合类型,用selectFrom
作为 * discriminant * 属性。如果你愿意,你可以直接写出这个类型:这将如预期的那样工作:
如果你有很多这样的键,那么你可能希望通过一些Map接口以编程的方式计算
TGenerateCommonResult
,这个接口只是将每个键与对应的值相关联:理想情况下,这个接口或者包含相同信息的东西应该已经存在于你的代码库中,你提供的例子没有做到这一点;最接近的是
ISetMapping
,但是那个接口的值类型不区分TGenerateSetA
和TGenerateSetB
,或者根本不关心那个类型,我在这里不担心这个,但是你可能想重构你的代码,以便保留和使用那个信息。无论如何,给定Map,我们可以将
TGenerateCommonResult
计算为 * 分布式对象类型 *(在ms/TS#47109中创造的术语),这是一个mapped type,我们立即用完整的键集对它执行index,以得到一个并集。本质上,如果你有一个类型函数F<K>
,其中K
是一个类似键的类型,并且你想在K
中的联合体上分布F
,你可以写{[P in K]: F<P>}[K]
,它把K1 | K2 | ... | KN
转换成F<K1> | F<K2> | ... | F<KN>
,在你的例子中,类型函数是{ selectFrom: K }
和GenerateCommonResultMapping[K]
的交集,所以我们想要的类型是您可以验证它的计算结果是否为
其在结构上与上面人工写出的版本相同。
Playground代码链接