我有两个类,A和B,每个类(ISA和ISB)都有一个谓词函数,还有一个数组arr,其中包含这两个类的几个实例.当使用谓词函数过滤数组时,它正确地仅返回请求的实例,并且在类型级别上简化为仅包含请求的类的数组:

class A { }
class B { }

const isA = (
    x: any
): x is A => {
    return x instanceof A;
};

const isB = (
    x: any
): x is B => {
    return x instanceof B;
};

const arr: Array<A | B> = [new A(), new A(), new B()]

const onlyA = arr.filter(isA) // correct type: const onlyA: A[]
const onlyB = arr.filter(isB) // correct type: const onlyB: B[]

我的目标是编写一个函数getInstance(),它接受一个带有字符串值"a"和/或"b"的数组,并且只返回这个/这些名称的实例(S),例如,getInstance(["a"])应该具有与上面的onlyA相同的返回值,getInstance(["a", "b"])应该返回A和B的实例,并且在类型级别(A | B)[]上.

我try 创建一个将字符串与谓词函数相关联的新对象Obj.我使getInstance()成为泛型,并将其唯一参数约束为键Obj.但是,此实现在类型级别上不起作用.

const Obj = {
    a: isA,
    b: isB
}


const getInstance = <T extends keyof typeof Obj>(types: T[]) => {
    const fns = types.map(type => Obj[type])
    const set = fns.map(fn => arr.filter(() => fn))

    return set.flat(1) 
}

const retA = getInstance(["a"]) // wrong return type: (A | B)[]; should return A[]
const retAB = getInstance(["a", "b"]) // should return (A | B)[]

推荐答案

TS5中有一个名为const Type Parameters的新功能

请注意以下几点修改:

  • 泛型参数现在是常量
  • 我将键作为变量,而不是数组
  • 您的筛选逻辑不正确
type TypeMap = {
  a: A
  b: B
}

const typePredicates = {
    a: isA,
    b: isB,
}

const getInstance = <const T extends keyof TypeMap>(...types: T[]): (TypeMap[T])[] => {
    const fns = types.map(type => typePredicates[type])
    const filtered = fns.flatMap(fn => arr.filter(fn))
    return filtered;  
}

const retA = getInstance("a");      // A []
console.log('RetA: ', retA);

const retAB = getInstance("a", "b") // (A | B)[]
console.log('RetAB: ', retAB);

Playground link

Javascript相关问答推荐

使用脚本标签时的JSDoc智能感知

使用Element.children在前后移动 node

为什么(1 + Number.Min_UTE)等于1?

Express.js:使用Passport.js实现基于角色的身份验证时出现太多重定向问题

如何访问react路由v6加载器函数中的查询参数/搜索参数

字节数组通过echo框架传输到JS blob

如何将连续的十六进制字符串拆分为以空间分隔的十六进制块,每个十六进制块包含32个二元组?

从WooCommerce Checkout Country字段重新排序国家,保持国家同步

如何在angular中从JSON值添加动态路由保护?

Msgraph用户邀请自定义邮箱模板

在观察框架中搜索CSV数据

如何在输入元素中附加一个属性为checkbox?

如何在Vue 3中创建自定义 Select 组件,并将选项作为HTML而不是props 传递?

更改预请求脚本中重用的JSON主体变量- Postman

类构造函数不能在没有用With Router包装的情况下调用

在Matter.js中添加从点A到另一个约束的约束

Google脚本数组映射函数横向输出

将多个文本框中的输出合并到一个文本框中

Next.js无法从外部本地主机获取图像

重新呈现-react -筛选数据过多