打字稿。如何从参数中获取对象中的属性类型作为返回类型

时间:2021-01-30 22:10:26

标签: typescript types properties return arguments

我希望你能帮助我使用 TypeScipt ;)

问题:

如何从从参数接收的对象属性中获取类型?

代码:

const someVariable = 'test=123&test2=456';

// I want by default return type { [key: string]: any }[],
// but if options.parse === false { [key: string]: string }[]
function someFunction(options: string | IOptions) {
  if (typeof options === 'string') {
    return someVariable.split('&').map((part) => {
      const [key, value] = part.split('=');
          
      return { [key]: JSON.parse(value) };
    });
  }

  return someVariable.split('&').map((part) => {
      const [key, value] = part.split('=');
          
      if (options.parse) {
        return { [key]: JSON.parse(value) };
      }
          
      return { [key]: value };
    });
}

someFunction()
// => { [key: string]: any }[]

someFunction({ parse: false })
// => { [key: string]: string }[]

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

实现此目的的一种方法是将 someFunction() 设为具有多个调用签名的 overloaded function,这些调用签名对应于您想要查看的不同输入-输出关系:

// call signatures
function someFunction(options: IOptions & { parse: false }): Array<{ [k: string]: string }>;
function someFunction(options: string | IOptions): Array<{ [k: string]: any }>;

// implementation
function someFunction(options: string | IOptions): Array<{ [k: string]: any }> {
  // impl unchanged
}

当你调用它时你可以看到它按预期工作:

const valAny = Object.values(someFunction("aString")[0])[0]
// const valAny: any

const valString = Object.values(someFunction({ parse: false })[0])[0]
// const valString: string

您也可以使用返回 genericconditional type 函数实现此结果:

function someFunction<T extends string | IOptions>(
    _options: T
): Array<{ [k: string]: T extends { parse: false } ? string : any }> {
   const options: string | IOptions = _options;
   // impl unchanged after this
}

对于我们上面测试的调用,它的行为方式相同:

const valAny = Object.values(someFunction("aString")[0])[0]
// const valAny: any

const valString = Object.values(someFunction({ parse: false })[0])[0]
// const valString: string

每种解决方案都有其优点和缺点,具体取决于用例。这两种解决方案都不能保证函数实现内部的类型安全,因此您需要注意实现确实符合您正在使用的调用签名。

Playground link to code

相关问题