请考虑以下代码段:
function doIt<K extends string>(key: K, arg: number): string {
return `key=${key}, arg=${arg}`;
}
// [A] Doesn't work, DoIt is no longer a generic!
// type DoIt = typeof doIt;
// I have to duplicate the signature of doIt here:
type DoIt<K extends string> = (key: K, arg: number) => string;
type ITextEntryBlock = {
[key: string]: { en: string; fr: string };
};
const textMap: ITextEntryBlock = {
body: {
fr: 'Bonjour {prefix} {firstname} {lastname}',
en: 'Dear {prefix} {firstname} {lastname}',
},
test: {
fr: 'FR {prefix} {firstname} {lastname}',
en: 'EN {prefix} {firstname} {lastname}',
},
};
// [B] Doesn't work: keyof typeof textMap
type Entries = 'body' | 'test';
const doItNarrowed: DoIt<Entries> = doIt;
console.log(doItNarrowed('body', 42));
console.log(doItNarrowed('test', 7));
// doItNarrowed('blah', 0); // fails, which is good
该代码段可以编译并运行,但是有两个问题,我已经用[A]
和[B]
标记了。
[A]
:在泛型函数上使用typeof
时,类型显然失去了通用性。使用DoIt<Entries>
声明DoIt
时typeof
失败。这很不幸,因为每次更改doIt
的签名时,我也必须更新类型DoIt
。
[B]
:我想声明type Entries = keyof typeof textMap
。这种工作方式有效,但是TypeScript还以某种方式添加了类型number
,并且DoIt<Entries>
将失败,因为number
不会扩展string
。因此,我必须明确声明Entries
,这很不幸,因为每次我向textMap
添加新密钥时,我也必须更新类型Entries
。
有没有办法解决这些问题?