缩小泛型函数的类型

时间:2020-07-21 13:24:41

标签: typescript generics indexing

请考虑以下代码段:

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>声明DoIttypeof失败。这很不幸,因为每次更改doIt的签名时,我也必须更新类型DoIt

[B]:我想声明type Entries = keyof typeof textMap。这种工作方式有效,但是TypeScript还以某种方式添加了类型number,并且DoIt<Entries>将失败,因为number不会扩展string。因此,我必须明确声明Entries,这很不幸,因为每次我向textMap添加新密钥时,我也必须更新类型Entries

有没有办法解决这些问题?

0 个答案:

没有答案