类型不能分配给条件类型 [英] Type is not assignable to conditional type

查看:139
本文介绍了类型不能分配给条件类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在操场上有一个TypeScript代码段.请看看那里打字稿游乐场或此处:

 枚举MyTypes {FIRST ="FIRST",SECOND ="SECOND",第三=第三"}输入TFirst = {类型:MyTypes.FIRSTfoo:字串}类型TSecond = {类型:MyTypes.SECONDfoo:字串}类型TThird = {类型:MyTypes.THIRD条:字符串}类型TConditionalType< T>=T扩展MyTypes.FIRST吗?TFirst:T扩展了MyTypes.SECOND吗?TSecond:T扩展MyTypes.THIRD吗?第三:空值const getMyObjectBasedOnType =< T扩展MyTypes>(类型:T):TConditionalType< T>|null =>{开关(类型){大小写MyTypes.FIRST:{返回 {类型:MyTypes.FIRST,foo:测试"}}默认: {返回null}}}const firstObject = getMyObjectBasedOnType(MyTypes.FIRST)//firstObject是TFirst的类型或可以为null的类型如果(firstObject){firstObject.foo} 

有一个函数 getMyObjectBasedOnType(type:T),该函数根据 type 参数返回条件类型的对象.这似乎可行,因为末尾的 firstObject 类型为 TFirst |.空.全部清除在这里.

我返回对象时,第31行中提到的函数内部存在TypeScript错误,这是我遇到的问题.我得到这个: Type'{type:MyTypes.FIRST;foo:字串;}"不能分配给"TConditionalType< T>"类型.我无法弄清楚出了什么问题.据我了解,这是 TFirst 的对象,应该没问题.为什么我会收到此错误?什么是正确的解决方法?

解决方案

关于您的问题,它来自于延迟的条件类型.查看打字稿文档: https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types .(推迟搜索条件类型以到达页面的正确位置.)

有关此设计决策的简短讨论: https://github.com/Microsoft/TypeScript/issues/29939 ..>

最简单的解决方案是使用一个更宽松的单独实现签名,同时将公共签名保留为对调用者更有利的条件类型:

  type TConditionalType< T>=T扩展MyTypes.FIRST吗?TFirst:T扩展了MyTypes.SECOND吗?TSecond:T扩展MyTypes.THIRD吗?第三:空值函数getMyObjectBasedOnType< T扩展了MyTypes>(类型:T):TConditionalType< T> ;;函数getMyObjectBasedOnType(type:MyTypes):TFirst |TSecond |TThird |空值 {开关(类型){大小写MyTypes.FIRST:{返回 {类型:MyTypes.FIRST,foo:测试"};//这里没有错}大小写MyTypes.SECOND:{返回 {类型:MyTypes.FIRST,foo:测试"};//不幸的是它将起作用...实现是允许的}默认: {返回null;}}}const firstObject = getMyObjectBasedOnType(MyTypes.FIRST)如果(firstObject){firstObject.foo;//它会工作firstObject.bar;//它将失败} 

我仍在弄清楚如何使其与箭头功能配合使用.要了解这两者之间的区别,您可以在这里参考:正确使用用于在JavaScript中定义函数的const的说明

I have a TypeScript code snippet in the playground. Please take a look there at TypeScript playground or here:

enum MyTypes {
    FIRST = "FIRST",
    SECOND = "SECOND",
    THIRD = "THIRD"
}

type TFirst = {
    type: MyTypes.FIRST
    foo: string
}

type TSecond = {
    type: MyTypes.SECOND
    foo: string
}

type TThird = {
    type: MyTypes.THIRD
    bar: string
}

type TConditionalType<T> =
    T extends MyTypes.FIRST ? TFirst :
    T extends MyTypes.SECOND ? TSecond :
    T extends MyTypes.THIRD ? TThird :
    null

const getMyObjectBasedOnType = <T extends MyTypes>(type: T): TConditionalType<T> | null => {
    switch (type) {
        case MyTypes.FIRST: {
            return {
                type: MyTypes.FIRST,
                foo: 'test'
            }
        }
        default: {
            return null
        }
    }
}

const firstObject = getMyObjectBasedOnType(MyTypes.FIRST)
// firstObject is type of TFirst or null which is okay
if (firstObject) {
    firstObject.foo
}

There is a function getMyObjectBasedOnType(type: T) which returns an object of a conditional type based on the type parameter. This seems to work since firstObject at the end is of type TFirst | null. All clear here.

Problem which I have is TypeScript error inside mentioned function on line 31 when I am returning object. I get this: Type '{ type: MyTypes.FIRST; foo: string; }' is not assignable to type 'TConditionalType<T>'. I can't figure it out what is wrong. As far as I understand it that is an object of TFirst which should be okay. Why do I receive this error and what is proper fix for it?

解决方案

Regarding your issue it comes from conditional types that are deferred. Look at the typescript documentation: https://www.typescriptlang.org/docs/handbook/advanced-types.html#conditional-types. (search for conditional types are deferred to get to the right place in the page).

There were some brief discussions about this design decision: https://github.com/Microsoft/TypeScript/issues/29939.

The simplest solution is to use a separate implementation signature that is more permissive, while keeping the public signature with conditional types that is better for the caller:

type TConditionalType<T> =
    T extends MyTypes.FIRST ? TFirst :
    T extends MyTypes.SECOND ? TSecond :
    T extends MyTypes.THIRD ? TThird :
    null

function getMyObjectBasedOnType<T extends MyTypes>(type: T): TConditionalType<T>; 
function getMyObjectBasedOnType(type: MyTypes): TFirst | TSecond | TThird | null {
  switch (type) {
    case MyTypes.FIRST: {
      return {
        type: MyTypes.FIRST,
        foo: "test"
      }; // nothing wrong here
    }
    case MyTypes.SECOND: {
      return {
        type: MyTypes.FIRST,
        foo: "test"
      }; // unfortunately it would work... The implementation is permissive
    }
    default: {
      return null;
    }
  }
}

const firstObject = getMyObjectBasedOnType(MyTypes.FIRST)
if (firstObject) {
    firstObject.foo; // it would work
    firstObject.bar; // it would fail

}

I'm still figuring out how to make it works with arrow functions. To know the difference between those two you can refer here: Proper use of const for defining functions in JavaScript

这篇关于类型不能分配给条件类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆