选择函数接受打字稿中的字符串或数组

时间:2019-06-14 05:09:09

标签: javascript typescript object

我想用打字稿写这个函数:

const pick = (obj, keys) => {
  if (!Array.isArray(keys)) keys = keys.split(',')
  return keys.reduce((acum, key) => (acum[key] = obj[key], acum), {})
}

const o = {
  a: 1,
  b: 2,
  c: 3
}

console.log('o[a,c]:', pick(o, 'a,c'))        // { a: 1, c: 3 }
console.log('o[a,c]:', pick(o, ['a', 'c']))   // { a: 1, c: 3 }

我已经看到this answer似乎是一个很好的起点,但我不知道如何将字符串转换为K []。

还是我可以以某种方式告诉Typescript信任我,并避免检查类型?

2 个答案:

答案 0 :(得分:1)

您可以使用工会

const pick = (obj: Object,  keys: string[] | string) => {
....
}

答案 1 :(得分:1)

Typescript编译器在使用拆分进行评估时不知道您的字符串是什么,因此您必须在其上强制使用K[],这将返回T的所有属性。

根据您的期望用法,只有第二种才可以获取期望的类型。

// i changed the "a" property to a string
const o = { a: 'hello', b: 2, c: 3 };

// <T, K extends keyof T> - here you assign the generics
// T - will be used on "obj" parameter so it can inherit it's properties
// K - will be a property of T
// I typed the "keys" parameter with "string" (to respect your first usage) and K[] (an array of K properties , for the second one)
// At last, we want the function to return K props of T, we have the Pick construct for that.
const pick = <T, K extends keyof T>(obj: T, keys: string | K[]): Pick<T, K> => {
    if (!Array.isArray(keys)) keys = (keys as string).split(',') as K[]; // we know that "keys" is a string, so we'll force the type on it, and we'll force K[] on the .split result, this will return all types from T.
    return keys.reduce((acum, key: K) => (acum[key] = obj[key], acum), {} as T ); // here we mark the accumulator as T, so we know what properties are used.
};

let p1 = pick(o, 'a,c'); // { a: string , b: number, c: number } - You'll get all the keys from obj
let p2 = pick(o, ['a','c']); // { a: string , c: number }