繁体   English   中英

Typescript 通用的两层联合类型推断

[英]Typescript two layer union type infer in generic

我想用 TypeScript 写一个小语言,我为它定义了基本数据类型:

type BasicDataType = {
    kind: 'text'
} | {
    kind: 'number'
};

然后我定义了一个泛型类型来表达它的实例:

type BasicInstance<B extends BasicDataType> = B extends { kind: 'number' } ?
    number
    : B extends { kind: 'text' } ?
    string
    : never;

let a: BasicInstance<{ kind: 'number' }> = 1;
let b: BasicInstance<{ kind: 'text' }> = '';

它运行良好,但是当我尝试定义高级类型及其实例时:

type DataType = {
    kind: 'single',
    t: BasicDataType
} | {
    kind: 'array',
    t: BasicDataType,
};
type Instance<D extends DataType> = D extends { kind: 'single', t: infer B } ?
    BasicInstance<B>
    : D extends { kind: 'array', t: infer B } ?
    Array<BasicInstance<B>>
    : never;

我得到了错误:

错误 TS2344:类型“B”不满足约束“BasicDataType”。 类型 'B' 不能分配给类型 '{ kind: "number"; }'。

似乎 TypeScript 无法理解 B 必须是 BasicDataType。 为什么会发生? 我该如何解决?

推断的类型并不总是像您期望的那样准确。 以这个类型定义为例:

type NotWorking<T extends {x: {y: number}}> =
  T extends {x: infer N} ? N['y'] : never

它因Type '"y"' cannot be used to index type 'N'. ,即使由于T extends {x: {y: number}}约束, N['y']应该存在。 要进行类型检查,您可以添加另一个条件N extends {y: number} ,它将始终通过:

type Working<T extends {x: {y: number}}> =
  T extends {x: infer N} ? N extends {y: number} ? N['y'] : never : never

对于您的类型,您可以在外部放置一个B extends BasicDataType额外条件并使用infer K作为类型,因此您只需要一个extends条件即可涵盖所有类型:

type Instance<D extends DataType> =
  D extends { kind: infer K, t: infer B }
  ? B extends BasicDataType
    ? K extends 'single' ? BasicInstance<B> 
    : K extends 'array' ? Array<BasicInstance<B>>
    : never
   : never
: never

TypeScript操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM