【问题标题】:pick function accepting string or array in typescript在打字稿中选择接受字符串或数组的函数
【发布时间】:2019-06-14 05:09:09
【问题描述】:

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

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 信任我,并且不要检查类型吗?

【问题讨论】:

  • 你试过铸造吗? keys =<K[]> keys.split(',')

标签: javascript typescript object


【解决方案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 }

【讨论】:

  • 很好的答案,有几个问题: - Pick 类型是否表示具有 T 属性子集的对象? - (keys as string)这是你在打字稿中的投射方式吗?
  • Pick 将在K 值存在于T 的条件下创建一个基于K 值的新类型,阅读utility types,它们非常方便,如果您想要更多阅读 @basaratTypeScript Deep Dive
  • (keys as string) 开始,它是在变量/函数/任何东西上强制使用类型。我在我的代码中使用它是因为编译器期望keysstring or K[],但是当我们到达.split 方法时,类型检查知道.split 是可以在string 上找到的方法类型,这没关系,但是当它检查 K[] 时它会失败,因为这种类型不是字符串,因此,使用 someVar as SomeType 你告诉打字稿编译器“YOU_KNOW_BETTER”,这绝对是你想要的类型检查,它会尊重你的类型。
【解决方案2】:

你可以使用联合

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-28
    • 2021-08-03
    • 2020-12-02
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多