typescript 类型保护函数不起作用,类型仍然被判断为字符串

nfg76nw0  于 2023-04-22  发布在  TypeScript
关注(0)|答案(2)|浏览(149)

我很困惑为什么有时我的类型保护功能不起作用。
例如,我有下面的类型保护函数。

enum Services {
  email = 'Email',
  cloud = 'Cloud',
  map = 'Map',
}

// this is ok.
const isValidService = (value: string): value is keyof typeof Services => {
  return value in Services;
}

// this doesn't work. 
const isKeyOfEnum = <T>(enumObject: T) => (value: string): value is keyof typeof T => value in enumObject;

并在下面的代码中使用它们

const handleServicesChange = useCallback((item: string) => {

    if (isValidService(item)) {
      // type of item is judged as 'email' | 'cloud' | 'map'
      console.log(Services[item]);
    }
  }, []);
const handleServicesChange = useCallback((item: string) => {
    const isServiceKey = isKeyOfEnum(Services);

    if (isServiceKey(item)) {
      // type of item still be judged as string ...
      console.log(Services[item]);
    }
  }, []);

那么为什么KeyOfEnum不能工作呢?如何重构它呢?

inb24sb2

inb24sb21#

这里有几件事:

// Original code
const isKeyOfEnum = <T>(enumObject: T) =>
  (value: string): value is keyof typeof T => value in enumObject;

首先-T是一个类型,所以TS报告typeof T试图使用类型作为值。只需使用T,而不是typeof T
TS然后报告Type 'keyof T' is not assignable to type 'string'。您的输入始终是string,但Assert的返回类型实际上将其削弱为string | number | symbol。好吧,只需将Assert的类型缩小为Extract<keyof T, string>
最后,value in enumObject显示一个错误:Type 'T' is not assignable to type 'object'. This type parameter might need an extends object constraint.很好,只需在T上添加建议的类型约束。
把它们放在一起,你会得到:

const isKeyOfEnum = <T extends object>(enumObject: T) =>
  (value: string): value is Extract<keyof T, string> => value in enumObject;

Playground

rxztt3cl

rxztt3cl2#

T已经是类型,一个泛型类型,所以value应该是keyof T而不是keyof typeof T
keyof运算符接受一个对象类型,并生成其键的字符串或数字文本并集。

const isKeyOfEnum = <T extends object>(enumObject: T) => (value: string): value is keyof T => value in enumObject;

相关问题