我在MessagesStore对象中实现条件类型时遇到打字错误.以下是完整的代码设置:

type Message = { id: number; text: string };

type MessagesStore = {
    queue: Array<Message>;
    read: <T extends boolean>(assertiveMode?: T) => T extends true ? Message : Message | undefined;
}

const store: MessagesStore = {
    queue: [],

    read(assertiveMode: boolean = false) {
        const message = this.queue.shift();

        if (assertiveMode && message === undefined) {
            throw new Error('The messages queue is empty');
        }

        return message;
    }
}

但是,TypeScrip会引发以下错误:

Type '<T extends boolean>(assertiveMode?: boolean) => Message | undefined' is not assignable to type '<T extends boolean>(assertiveMode?: T | undefined) => T extends true ? Message : Message | undefined'.
  Type 'Message | undefined' is not assignable to type 'T extends true ? Message : Message | undefined'.
    Type 'undefined' is not assignable to type 'T extends true ? Message : Message | undefined'.

我很难理解为什么我会收到这个错误,以及如何解决它.

推荐答案

目前,从TypeScrip 5.3开始,还没有编译器验证的类型安全方法来返回依赖于generic类型参数的conditional type.在microsoft/TypeScript#33912中有一个长期开放的特性请求来支持这一点,但目前它还不是语言的一部分.

目前的问题是,当你判断assertiveMode时,它可以将assertiveMode的类型从T缩小到truefalse,但它对泛型类型参数T本身没有任何影响.这保持不变,所以编译器仍然不能判断message是否是类型T extends true ? Message : Message | undefined的合适值.

有可能很快就会解决这个问题;在microsoft/TypeScript#56941有一个拉请求,它可能在某个时候被合并,我看到处理这些类型的泛型函数是在TypeScrip5.5的microsoft/TypeScript#57475的路由图上.因此,您的代码可能会奇迹般地开始工作,没有任何错误.

除非发生这种情况,否则您将需要放松类型判断以编译您的代码.要做到这一点,最简单的方法是用the any type表示我们根本不想判断返回类型:

const store: MessagesStore = {
  queue: [],

  read(assertiveMode: boolean = false) {
    const message = this.queue.shift();

    if (assertiveMode && message === undefined) {
      throw new Error('The messages queue is empty');
    }

    return message as any; // 🤷‍♀️ ms/TS#33912
  }
}

这很不幸,但就目前而言,泛型条件返回类型更适用于函数callers,而不是函数implementers.

Playground link to code

Typescript相关问答推荐

如何在函数参数中使用(或模仿)`success`的行为?

类型脚本接口索引签名

类型{}上不存在属性&STORE&A;-MobX&A;REACT&A;TYPE脚本

获取函数中具有动态泛型的函数的参数

类型脚本满足将布尔类型转换为文字.这正常吗?

如何使所有可选字段在打印脚本中都是必填字段,但不能多或少?

为什么在leetcode问题的测试用例中,即使我确实得到了比预期更好的解决方案,这段代码也失败了?

专用路由组件不能从挂钩推断类型

在Cypress中,您能找到表格中具有特定文本的第一行吗?

是否可以通过映射类型将函数参数约束为预定义类型?

打字脚本中的模块化或命名空间

我不明白使用打字脚本在模板中展开参考

如何为带有参数的函数类型指定类型保护?

如何在Reaction Native中关注屏幕时正确更新状态变量?

可以用任意类型实例化,该类型可能与

Typescript不允许在数组中使用联合类型

映射类型不是数组类型

Typescript泛型-键入对象时保持推理

两个子组件共享控制权

将对象数组传递给 Typescript 中的导入函数