TypeScript条件类型抱怨类型不可分配

时间:2019-04-11 21:56:02

标签: typescript

我试图了解TypeScript条件类型的工作方式。这是我的代码。有类型错误:

interface MyType {
  name: string;
}

const testFunc = <T extends MyType | string>(
  what: T
): T extends MyType ? MyType : string => {
  if (typeof what === 'object') {
    return what['name'];
  }
  return what;
};

正确用法是什么?

enter image description here

enter image description here

3 个答案:

答案 0 :(得分:1)

我会这样:

interface MyType {
  name: string;
}

const testFunc = <T>(what: T): T extends MyType ? MyType : string => {
    if (typeof what === 'object') {
        return what['name'];
    } 
    return what as any;

};

as any的意思是“ TypeScript,不要抱怨这种类型”。问题在于条件类型不会选择what的缩小类型,因此该函数无法评估条件并将返回类型缩小到what

答案 1 :(得分:1)

  

此答案基本上是用更多的单词和代码解释@jcalz的comment

您正确理解了这个概念。不幸的是,您在TS中遇到了警告,在通过控制流分析来缩小可能性时,它不会平等地对待具体类型和通用类型。

理想情况下,您建议的用法应该是有效的。但是TS doesn't support it yet

目前,我们需要解决方法,这是我通常要做的。

interface MyType {
  name: string;
}

const testFunc = <T extends MyType | string>(
  _what: T
): T extends MyType ? MyType : string => {
  // First thing to do once enter the fn body,
  // we manually cast to `any` type
  var what = _what as any;
  if (typeof what === 'object') {
    return what['name'];
  }
  return what;
};

不完美,我知道。有点像您实现了一个重载函数,最终您只需要使用any类型。但是,由于您已经为消费者提供了完善的功能界面,因此可以在后台稍作改动。

答案 2 :(得分:1)

在每种情况下,代码中的函数TestFunc应该返回string。我认为这是一种错字。让我们对其进行修复,然后继续使其按自己的意愿去做。这将更接近原始代码:

interface MyType {
  name: string;
}

type TestFunc = <T extends MyType | string>(what: T) => T extends MyType ? string : MyType;

const testFunc: TestFunc = (what: any) => {
  if (typeof what === 'object') {
    return what.name;
  }
  return { name: what };
};

或者,如果您希望内联定义类型:

interface MyType {
  name: string;
}

const testFunc: <T extends MyType | string>(what: T) =>
  T extends MyType ? string : MyType =
  (what: any) => {
    if (typeof what === 'object') {
      return what.name;
    }
    return { name: what };
  };

Typescript编译器将按以下方式处理它:

const a1: MyType = testFunc({ name: 'foo' }); // Type 'string' is not assignable to type 'MyType'.

const a2: MyType = testFunc({ name: 1 }); // Error: Argument of type '{ name: number; }'
//                                is not assignable to parameter of type 'string | MyType'

const a3: string = testFunc({ name: 'foo' }); // Ok

const a4: string = testFunc('foo'); // Error: Type 'MyType' is not assignable to type 'string'.

const a5: MyType = testFunc('foo'); // Ok
相关问题