Typescript 控制流分析无法识别已知类型

标签 typescript

我试图理解为什么需要明确告诉编译器 Policies 中的值的类型。类型是,尽管它只能是我的 Types 之一。

type Types = 'baz' | 'bar';

// tagged union types
type Foo<T extends Types> = { type: T; }
type FooOne = { one: string } & Foo<'baz'>;
type FooAnother = { another: string } & Foo<'bar'>;

type Predicate<T extends Types> = (e: Foo<T>) => boolean;

type Policies = {
    [P in Types]: Predicate<P>
}

const policies: Policies = {
    baz: (e: FooOne) => e.one === 'neo',
    bar: (e: FooAnother) => e.another === 'morphieus'
}

// this method receives a union type
function verify(e: FooOne | FooAnother) {
    // these both work, understandably
    if (e.type === 'baz') {
        const policy1 = policies[e.type]; // ide says this type is a Predicate<'baz'>
        const result1 = policy1(e); // fine  
    } else {
        const policy2 = policies[e.type]; // and this is a Predicate<'bar'>
        const result2 = policy2(e); // fine
    }

    // but this doesn't work even though e.type is known to be 'baz' | 'bar', and the keys at policies can only be 'baz' | 'bar'
    const policy3 = policies[e.type]; // ide says this type is a Predicate<'bar'> | Predicate<'baz'>
    const result3 = policy3(e); // error Cannot invoke an expression whose type lacks a call signature  

    // this works, if i hint to the compiler what is at policies[T]
    const policy4: Predicate<Types> = policies[e.type]; // Predicate<'baz' | bar'>
    const result4 = policy4(e); // fine 
}

最佳答案

这里没有好的解决方案,您需要某种类型断言才能使事情正常工作。

问题在于流分析无法跟踪值的来源。所以当你写:

const policy3 = policies[e.type]; 
const result3 = policy3(e);

policy3将是Predicate<"baz"> | Predicate<"bar">但编译器不知道是哪一个。当您调用policy3时因为它不知道变量中实际上是哪种函数类型,所以在较新的版本中,它将强制您指定一个可以与联合中的任一函数一起使用的参数。它不记得policy3 si 实际上绑定(bind)到 e.typepolicy3(e)将是类型安全的。 (仅供引用:在旧版本中 policy3 根本无法调用,因为它是一个联合)

此代码有效:

const policy4= policies[e.type] as Predicate<Types> ; // Predicate<'baz' | bar'>
const result4 = policy4(e); // fine 

但是Predicate<"baz"> | Predicate<"bar">Predicate<Types> 不同。前者是一个需要 baz 的函数或采用 bar 的函数后者是一个函数,它接受 bazbar 。因此,该调用将起作用,因为您已断言该函数可以接受任一参数类型(这并不完全正确,但就像我所说的没有好的解决方案)。

关于Typescript 控制流分析无法识别已知类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54575849/

相关文章:

typescript - 使用 CDK 将文件上传到 S3 存储桶

Angular2 将纯文本转换为 url( anchor 链接)的方法

javascript - angular 6 自定义元素在 IE11 和 Firefox 上失败,出现语法和影子 dom 错误

angular - 如何使用 react 形式从输入中获取字符串

javascript - 要求未在反射元数据上定义 - __webpack_require__ 问题

javascript - 在 Angular 2 App 中缓存组件数据

angular - 从 Angular 2 中的子组件更新父组件属性

javascript - 在 typescript 中使用变量作为方法

javascript - Typescript 中的 new() 是什么?

angular - Angular 2 模板中的类型检查