这是上一个关于类似主题的问题的largely a follow up,但已简化了一点。
基本上,我想做的是通过转换器函数传递对象的参数和值(它将是一个工厂生成器,但是我在这里简化了将数字更改为字符串,反之亦然),然后将这些属性分配给该对象返回并保持输入。
这是我一直在尝试的代码:
type Config<T extends {[key:string]: number | string}> = {
inst?: T
}
function convert ( value: string ): number;
function convert ( value: number ): string
function convert( value: any ): any {
if ( typeof value === 'number' ) {
return value.toString();
}
return parseInt( value.toString(), 10 );
}
function init<T extends {[key:string]: any}>(db, config: Config<T>): T & {} {
let ret: any = {};
if ( config.inst ) {
for (let [key, value] of Object.entries(config.inst)) {
let res = convert( value );
ret[ key ] = res;
}
}
return ret;
}
let a = convert( '1' ); // `a` is a `number`
let b = convert( 2 ); // `b` is a `string`
let { strToNum, numToStr } = init( null, { inst: { strToNum: '1', numToStr: 2 } } );
// `strToNum` is a string - should be a number
// `numToStr` is a number - should be a string
convert函数对于重载类型似乎可以正常工作,但是我一生都无法弄清楚如何使类型适用于返回的对象的参数。有什么想法吗?
答案 0 :(得分:2)
您基本上想将conditional types(代表从string
到number
的切换,反之亦然)与mapped types(代表每个属性上的此切换)结合在一起:< / p>
type Convert<T extends string | number> = T extends number ? string : number;
declare function init<T extends { [key: string]: any }>(
db: any,
config: Config<T>
): {[K in keyof T]: Convert<T[K]>};
并尝试:
let { strToNum, numToStr } = init(null, { inst: { strToNum: '1', numToStr: 2 } });
strToNum.toFixed(0); // okay
numToStr.charAt(0); // okay
看起来不错。
顺便说一句,您也可以使用条件类型来表示您的convert()
函数,出于某些目的,它可能比多重重载更可取:
function convert<T extends string | number>(value: T): Convert<T>;
function convert(value: string | number): string | number {
if (typeof value === 'number') {
return value.toString();
}
return parseInt(value.toString(), 10);
}
convert(Math.random()<0.5 ? "1" : 2); // string | number
// the above will fail with overloads
希望有所帮助;祝你好运!