TS泛型约束报错,if语句里面已经能推断出来T是string类型,但为什么还是报错了?

function test<T extends string | string[]>(params: T): T {
  if (typeof params ==='string') {
    return ''
  } else {
    return ['']
  }
}

image.png

if语句里面已经能推断出来T是string类型,但为什么还是报错了

回复
阅读 1.4k
4 个回答

Typescript 的类型缩小是针对常规变量的,即使 params 是字符串,也不能将 T 缩小为字符串类型。可以使用类型断言指定类型。

function test<T extends string | string[]>(params: T): T {
  if (typeof params === "string") {
    return "" as T;
  } else {
    return [""] as T;
  }
}

T extends string | string[]不是说T只能是stringstring[],比如ts中还有一种类型叫元组——type Tuple = ['特定的值'],它符合泛型的约束,但是你的代码里return的值并不符合这个元组的约束.

在这个方法里面 ts 认为 params类型是T
但是 硬编码的 " " 和 [" "] 不是 T
所以你需要额外的类型断言 或者 函数参数重载

简化一下把参数,Union数组类型和字面量''全干掉 一样还是会报错的

function test<T extends string>(): T {
    return String('')
}

最主要的原因是这个函数的两个约束发生了冲突:
(1)<T extends string> T可以是string任何的subtype, string 就是 T的约束
(2)return String('')():T 说明 T的类型是string
然后就出现了图中错误的描述: 尽管(由于2)我们可以把string赋值给T类型, 但是(由于1)T也可以是string的其他任何子类型, 显然这样的定义是矛盾的.
也就是说你本身的函数定义就是矛盾的, 因为这个T没有任何拓展的空间, 这里它只能等于():string