【问题标题】:TypeScript: Tell TypeScript a function checks for `typeof !== undefined`TypeScript:告诉 TypeScript 一个函数检查 `typeof !== undefined`
【发布时间】:2020-02-06 05:25:11
【问题描述】:

我如何让 TypeScript 知道一个函数验证了一个项目是否包含给定的键?

例如:

function doesItemHaveKey(item: any, key: string): boolean {
  return typeof item === 'object' && item !== null && typeof item[key] !== 'undefined';
}

interface testInterface {
  optional?: string;
  some: string;
}

let testObj: testInterface = {
  some: 'value'
};

if (doesItemHaveKey(testObj, 'some')) {
  // Do something with testObj.some
  // TypeScript throws errors because `testObj.some` could be undefined
}

我尝试过的事情:

if (doesItemHaveKey(testObj, 'some') && typeof testObj.some !== 'undefined') {
  // This works, but duplicates the typeof check
}

function doesItemHaveKey(item: any, key: string): key is keyof item
/**
 * A type predicate's type must be assignable to its parameter's type.
 *  Type 'string | number | symbol' is not assignable to type 'string'.
 *    Type 'number' is not assignable to type 'string'.
 **/

【问题讨论】:

  • 我想你忘了一个?在some 上,否则some 不是可能未定义的类型
  • 即使它是可选的,testObj.some 也不会在该代码中给出类型错误。

标签: typescript


【解决方案1】:

类型断言版本可以工作,您只需要添加一些泛型类型参数来捕获item 类型(在T)和实际类型(在K)。然后,您可以使用 type-guard 语法告诉编译器 item 参数是 T 在需要键 K 的交集中(这将有效地使键 K 必需)

function doesItemHaveKey<T, K extends keyof T>(item: T, key: K): item is T & Required<Pick<T, K>> {
  return typeof item === 'object' && item !== null && typeof item[key] !== 'undefined';
}

interface testInterface {
  optional?: string;
  some?: string;
}

let testObj: testInterface = {
  some: 'value'
};

if (doesItemHaveKey(testObj, 'some')) {
  testObj.some.big() // string 
}

Playground Link

【讨论】:

    【解决方案2】:

    您可以将doesItemHaveKey 设为user-defined type guard,使用泛型类型参数和Exclude 构造T 的子类型,其中键K 的值不是undefined

    type NotUndefined<T, K extends keyof T> = T & Record<K, Exclude<T[K], undefined>>;
    
    function doesItemHaveKey<T, K extends keyof T>(item: T, key: K): item is NotUndefined<T, K> {
        return typeof item === 'object' && item !== null && typeof item[key] !== 'undefined';
    }
    

    Playground Link

    【讨论】:

    • 与公认的答案不同,这个答案对我有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 2019-03-31
    • 2022-11-17
    • 2020-07-27
    • 2019-03-27
    • 1970-01-01
    相关资源
    最近更新 更多