使用TypeScript推断嵌套对象中的返回类型

时间:2018-11-06 14:44:10

标签: typescript

这是上一个关于类似主题的问题的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函数对于重载类型似乎可以正常工作,但是我一生都无法弄清楚如何使类型适用于返回的对象的参数。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您基本上想将conditional types(代表从stringnumber的切换,反之亦然)与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

希望有所帮助;祝你好运!