Typescript泛型函数,因此类型推断和代码提示将起作用

时间:2018-12-13 11:16:58

标签: typescript

这是我需要在Typescript中定义的函数调用

gen(settings: ISettings, enabled?: object, maps?: object): (v: string) => string;

其中的设置是:

interface ISettings {
    mods: string[];
    states: string[];
}

但是ISettings中的数组值实际上与函数调用中的其他两个参数有关:enabledmap

也许更好地理解一个例子。

gen({
        mods: ['one', 'two'],
        states: ['init', 'final']
    }, {
        one: true,
        init: true
    }, {
        one: 'first',
        two: 'second',
        final: 'end'
    }
);

如您所见:

  • 第一个对象中的数组项代表第二个和第三个参数对象的对象键,属于这些键的一部分
  • 第二个对象使用数组键的子集,值是布尔值
  • 第三个对象使用数组键的子集,值是字符串

就我所获得的代码而言,但这是行不通的。我希望代码完成建议第二个和第三个参数对象中的对象键,因为它们与第一个参数对象中的那些数组有关。

interface ISettings<TMods extends object, TStates extends object> {
    mods: Array<keyof TMods & string>;
    states: Array<keyof TStates & string>;
    [other: string]: any;
}

function gen<
    TMods extends object = {},
    TStates extends object = {}
>(
    settings: string | ISettings<TMods, TStates>,
    enabled: Partial<Record<keyof (TMods & TStates), boolean>> = {},
    maps: Partial<Record<keyof (TMods & TStates), string>> = {}
): string {
    //function doesn't return anything yet
    return '';
}

gen({
    mods: ['one', 'two'],
    states: ['disabled', 'fixed']
}, {
    one: true,
    disabled: true
}, {
    one: 'first',
    two: 'second',
    fixed: 'static'
});

从建议的类型可以看出,enabledmaps参数可以定义settings中提供的两个字符串数组的组合的成员的任何子集(或全部)宾语。这两个对象可以具有重叠的成员。

Partial<Record<keyof (TMods & TStates), ...>>
  • settings参数定义了可能的对象成员,但是由于它们在函数体内的使用方式不同,它们被分成两个字符串数组
  • enabled对象将某些成员设置为 on
  • maps对象更改其输出名称(重新映射原始名称);输出将仅返回并重新映射启用了启用标志的输出。
  

注意 :该代码基本上是试图为npm libs的suit-cx.d.tsbem-classnames.d.ts文件的代码定义如果您熟悉它们,则使用相同的名称。

1 个答案:

答案 0 :(得分:0)

稍微简化类型,以便编译器仅需将键推断为字符串文字类型(而不是其他未知对象的键),就可以让编译器在编写第二和第三个参数时提供一些建议:

interface ISettings<TModsKeys extends string, TStatesKeys extends string> {
    mods: Array<TModsKeys>;
    states: Array<TStatesKeys>;
    [other: string]: any;
}

function gen<
    TModsKeys extends string,
    TStatesKeys extends string
>(
    settings: string | ISettings<TModsKeys, TStatesKeys>,
    enabled: Partial<Record<TModsKeys | TStatesKeys, boolean>> = {},
    maps: Partial<Record<TModsKeys | TStatesKeys, string>> = {}
): string {
    //function doesn't return anything yet
    return '';
}

gen({
    mods: ['one', 'two', 'three'],
    states: ['disabled', 'fixed']
}, {
    one: true,
    disabled: true,
}, {
    one: 'first',
    two: 'second',
    fixed: 'static',
});