typescript - Typescript 通用函数,以便类型推断和代码提示起作用
问题描述
这是我需要在 Typescript 中定义的函数调用
gen(settings: ISettings, enabled?: object, maps?: object): (v: string) => string;
设置在哪里:
interface ISettings {
mods: string[];
states: string[];
}
但是 中的数组值ISettings
实际上与函数调用中的另外两个参数有关:enabled
和map
。
也许举个例子会更好理解。
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'
});
从提议的类型可以看出,enabled
和参数可以定义对象maps
中提供的两个字符串数组组合的任何成员子集(或完整) 。settings
这两个对象可以有重叠的成员。
Partial<Record<keyof (TMods & TStates), ...>>
- 该
settings
参数定义了可能的对象成员,但它们被拆分为两个字符串数组,因为它们在函数体内的使用方式不同 - 对象设置
enabled
某些成员 - 对象更改其
maps
输出名称(重新映射原始名称);输出只会返回并重新映射那些启用了标志的。
注意:此代码基本上是尝试为同名的 npm 库的
suit-cx.d.ts
和文件定义代码,如果您熟悉它们的话。bem-classnames.d.ts
解决方案
稍微简化类型,以便编译器只需将键推断为字符串文字类型(而不是作为另一个未知对象的键),编译器可以在编写第二个和第三个参数时提供建议:
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',
});