了解条件类型的类型推断

Posted

技术标签:

【中文标题】了解条件类型的类型推断【英文标题】:Understanding type inference with conditional types 【发布时间】:2022-01-17 21:49:25 【问题描述】:

我很难理解为什么 TypeScript 将这里的 program.options 推断为 ProgramAOptions | ProgramBOptions。因此它无法编译代码,因为optAProgramBOptions 中不存在。你能解释一下或指向我解释这种行为的文档吗?

type ProgramName = 'a' | 'b';

type ProgramAOptions = 
    optA: number;
;

type ProgramBOptions = 
    optB: number;
;

type Program<T extends ProgramName> = 
    name: T;
    options: T extends 'a' ? ProgramAOptions : ProgramBOptions;
;name

function test(p: Program<ProgramName>) : void

    if (p.name === 'a')
    
        p.options.optA = 10; /* this line would not compile with error:

        error TS2339: Property 'optA' does not exist on type 'ProgramAOptions | ProgramBOptions'.
        Property 'optA' does not exist on type 'ProgramBOptions'.*/
    

【问题讨论】:

【参考方案1】:

通过为每对名称和选项显式声明接口,我将通过以下方式解决您的问题:

type ProgramName = 'a' | 'b';

interface ProgramAOptions 
    optA: number;
;

interface ProgramBOptions 
    optB: number;
;

type ProgramOptions = ProgramAOptions | ProgramBOptions;

interface Program 
    name: ProgramName;
    options: ProgramOptions;


interface ProgramA extends Program 
    name: 'a';
    options: ProgramAOptions;


interface ProgramB extends Program 
    name: 'b';
    options: ProgramBOptions;


type Programs = ProgramA | ProgramB;

function test(p: Programs): void 
    if (p.name === 'a') 
        p.name // is of type "a"
        p.options.optA = 10; // Works
    

TypeScript playground

【讨论】:

这确实很好用,+1,不过我很想知道为什么“条件类型”的方式不行。 因为type narrowing 适用于单个变量和联合类型。在您的情况下,您有一个通用类型,您在其中为自己提供了 T 类型,因此您没有空间缩小类型

以上是关于了解条件类型的类型推断的主要内容,如果未能解决你的问题,请参考以下文章

条件类型中的 TypeScript 类型推断

Typescript 推断的泛型类型在条件类型中是未知的

Typescript 和 React:使用 React.Component 和条件类型化道具时类型推断失败

活用 Swift 类型推断

join 子句中的表达式之一的类型不正确。对“加入”的调用中的类型推断失败。-具有多个条件的 Linq JOIN

TypeScript 参数类型推断失败