ts函数泛型约束没用?

新手上路,请多包涵
function firstElement<Type>(arr: Type[]): Type {
  return arr[0];
}

let ele = firstElement<number>([]);

ele.toFixed();

传入firstElement为空数组的时候,返回值是个undefined,不符合泛型约束,为啥ts没有提示报错
有大佬给解答下吗

阅读 2.3k
2 个回答

ts只是校验编译时的类型,不会去校验运行时的表现。
Type[]的意思是,变量是一个数组,且数组里的值(如果有的话)都是Type
空数组也符合Type[],也就是说从类型角度来说arr[0]只可能是Type【至于实际运行时是不是那不是编译时的类型校验能做的,毕竟你还可以用as等方式绕开】。

假设如下代码:

function firstElement<Type>(arr: Type[]): Type {
  return arr[0];
}
let arr: number[] = [1]
remove(arr, 0)
let ele = firstElement(arr);

ele.toFixed();

function remove(arr: any[], index: number) {
    arr.splice(index, 1)
}

firstElement之前有个remove的操作,等到执行到时arr就已经没有元素了。这里ts同样推断不出undefined,因为这是程序运行时的行为。类型检查只检查类型,跟实际运行是没有关系的,你这里虽然是空数组,但是不能把它当值看,你得转成类型的角度来看:
首先,指定了泛型Typenumber,空数组为never[]
又因,never[]可以赋给number[]
故符合类型约束。
至于实际执行能不能取到值那不是ts做的,ts只检查数据类型对不对。可能讲的有点饶,总之就是类型就从类型的角度看.

const arr: never[] = []
const num: number[] = arr; // ok

因为你取数组里的某个值return,显然是有可能不存在的,所以你的返回值应该是Type|undefined这样就可以了。
又或者如果你是希望ts帮你校验出传入的数组不能是空数组,那你可以使用元组:

function firstElement<Type>(arr: [Type, ...Type[]]): Type {
  return arr[0];
}

let ele = firstElement<number>([]); // error

ele.toFixed();

你传入了一个 [],此时Type[]被推断为undefined[],函数返回的也是 undefined,没毛病。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进