我的目标是创建一个以2个字符串数组为参数的函数,并且第二个字符串数组不应包含第一个字符串数组的元素:

function doSomething<
    const T extends string,
    const K extends StringExcept<T>
>(
    firstArray: T[],
    secondArray: K[]
) {}

doSomething(['a', 'b'], ['c', 'b'])  // 'b' in the second array should cause type error

首先,我想我需要一个像type StringExcept<T>这样的类型,它应该是这样工作的:

type NotAbc = StringExcept<'abc'>;
const notAbcArray:NotAbc[] = [
    'any string',   // okay
    '123',          // okay
    'abc'           // not allowed
]

我试过的是使用Exclude<>型,比如Exclude<string, 'abc'>,但它不是这样工作的,只给出了string型.此外,我还try 了不同的变体,如T extends K ? never : T语句,但后来我发现类型排除的功能完全相同

然后我发现了this个问题,说像StringExcept这样的类型目前在TS中是不可能的(但如果有一些更新,我想知道).我也看了this个实验部分,现在已经关闭了.

那么,有没有办法让我的doSomething(firstArray, secondArray)发挥作用,不管是不是使用StringExcept这样的类型?

推荐答案

您可以在secondArray类型本身中使用the Exclude utility type:

function doSomething<
  const T extends string,
  const U extends string
>(
  firstArray: T[],
  secondArray: Exclude<U, T>[]
) { }

这将导致U被推断为secondArray的元素,然后checkedExclude<U, T>:

doSomething(['a', 'b'], ['c', 'd']); // okay

doSomething(['a', 'b'], ['c', 'b']); // error! 
// -------------------------> ~~~
// Type '"b"' is not assignable to type '"c"'.

这是可行的,因为TU都将(希望)是字符串literal typesunion,并且Exclude可以过滤这样的并集(而它不能过滤像string本身这样的非并集类型).

如果我们可以将Exclude<U, T>放在Uconstaint中,那就更好了,就像const U extends string & Exclude<U, T>一样,但编译器认为这是非法循环.所以我们可以将其下移到参数类型.

Playground link to code

Typescript相关问答推荐

类型安全JSON解析

将props传递给子组件并有条件地呈现它''

material 表不渲染任何数据

路由链接不会导航到指定router-outlet 的延迟加载模块

返回具有递归属性的泛型类型的泛型函数

如何在编译时为不带常量的参数引发错误

是否可以从函数类型中创建简化的类型,go 掉参数中任何看起来像回调的内容,而保留其余的内容?

如何从扩展接口推断泛型?

Fp-ts使用任务的最佳方法包装选项

如何使用模板继承从子组件填充基础组件的画布

编译TypeScrip项目的一部分导致错误

如何键入派生类的实例方法,以便它调用另一个实例方法?

在抽象类构造函数中获取子类型

如何正确地将元组表格输入到对象数组实用函数(如ZIP)中,避免在TypeScrip 5.2.2中合并所有值

TaskListProps[]类型不可分配给TaskListProps类型

如何创建由一个帐户签名但使用另一个帐户支付的Hedera交易

使用泛型以自引用方式静态键入记录的键

如何使用 AWS CDK 扩展默认 ALB 控制器策略?

覆盖高阶组件中的 prop 时的泛型推理

TS2532:对象可能未定义