繁体   English   中英

如何在 TypeScript 中缩小这种类型?

[英]How to narrow this type in TypeScript?

以下示例代码未通过类型检查。 如果可能的话,我想找到一种方法让它通过而as铸造。

type SupportedHandlerType = string | number | Date
type Handler<T> = (data: T[]) => void

function example<T extends SupportedHandlerType>(data: T[]) {
  const handler = getHandler(data)
  handler(data)
}

function stringHandler(data: string[]) {

}

function numberHandler(data: number[]) {
    
}

function dateHandler(data: Date[]) {
    
}

function getHandler<T>(data: T[]): Handler<T> {
    const first = data[0]
    if (typeof first == 'string') {
        return stringHandler // Type 'T' is not assignable to type 'string'
    }
    if (typeof first == 'number') {
        return numberHandler // another error here
    }
    return dateHandler // and here
}

我的现实生活版本要复杂得多,但这个简单的部分显示了我遇到的问题:我有几个类型形成一个联合( SupportedHandlerType ),通用 function 被其中一个调用。 我有一个getHandler() ,它动态查看类型以确定它是哪个类型并返回适当的处理程序 function,它有一个专用类型而不是T

有没有办法以某种方式缩小类型,以免出现诸如Type 'T' is not assignable to type 'string'错误?

操场

Arrays 一旦被转译为 javascript,就会丢失它们的类型。 这意味着,您无法确定数组的类型是什么,除非您遍历它们并检查每个元素的值。

这就是为什么我要添加这两个功能。

function isArrayOfStrings(value: unknown): value is string[] {
  return Array.isArray(value) && value.every(item => typeof item === "string");
}

function isArrayOfNumbers(value: unknown): value is number[] {
  return Array.isArray(value) && value.every(item => typeof item === "number");
}

更重要的是,请注意这些函数的返回类型。 这些函数有时被称为“类型保护”。 ... is... return-value-type 表示当 function 返回 true 时,这也意味着我们可以断定输入变量是某种类型。

最后,我将某些内容更改为T泛型。 你可以让它们extend一些东西。 通过这样做,我简化了 generics 并指出输入T应该始终是一个数组。

type Handler<T extends any[]> = (data: T) => void

function getHandler<T extends any[]>(data: T): Handler<T> {
  if (isArrayOfStrings(data)) {
    return stringHandler;
  }
  if (isArrayOfNumbers(data)) {
    return numberHandler;
  }
  return dateHandler;
}

或者,如果您不想遍历整个 arrays,您可以通过检查第一个元素的类型来简化isArrayOf...函数。

该问题与您如何声明处理程序函数有关。 您必须坚持在type Handler中声明的相同结构

type SupportedHandlerType = string | number | Date
type Handler<T> = (data: T[]) => void

function example<T extends SupportedHandlerType>(data: T[]) {
  const handler = getHandler(data)
  handler(data)
}

function stringHandler<T = string>(data: T[]) {

}

function numberHandler<T = number>(data: T[]) {
    
}

function dateHandler<T = Date>(data: T[]) {
    
}

function getHandler<T>(data: T[]): Handler<T> {
    const first = data[0]
    if (typeof data == 'string') {
        return stringHandler // Type 'T' is not assignable to type 'string'
    }
    if (typeof data == 'number') {
        return numberHandler // another error here
    }
    return dateHandler // and here
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM