[英]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.