typescript - 从数组的泛型推断正确类型的问题
问题描述
在以下示例中,我很难弄清楚如何缩小推断类型。目前,所有格式函数都接受string | number | boolean
并期望返回string | number | boolean
.
理想情况下,我想根据typeID
.
enum TypeID {
Number = "__number__",
String = "__string__",
Boolean = "__boolean__"
}
type Type<TYPE_ID extends TypeID> = {
[TypeID.Number]: number;
[TypeID.String]: string;
[TypeID.Boolean]: boolean;
}[TYPE_ID];
type Item<
TYPE_ID extends TypeID,
TYPE extends Type<TYPE_ID> = Type<TYPE_ID>
> = {
typeID: TypeID;
format: (input: TYPE) => TYPE;
};
type Options<TYPE_ID extends TypeID> = Array<Item<TYPE_ID>>;
const someFunc = <TYPE_ID extends TypeID>(options: Options<TYPE_ID>) => {
return null as any;
};
someFunc([
{
typeID: TypeID.Number,
format: input => input // these should have type "number"
},
{
typeID: TypeID.Boolean,
format: input => input // these should have type "boolean"
},
{
typeID: TypeID.String,
format: input => input // these should have type "string"
}
]);
解决方案
TYPE
拥有如此相似的类型名称( vs Type
vs TYPE_ID
vs )非常令人困惑,TypeID
所以我将在接下来的内容中使名称不同......对于泛型参数,我使用一两个大写字母(无论出于何种原因,这是惯例)。这是Type
:
type Type<T extends TypeID> = {
[TypeID.Number]: number;
[TypeID.String]: string;
[TypeID.Boolean]: boolean;
}[T];
这是Item
:
type Item<T extends TypeID> = {
typeID: T; // <-- T, not TypeID
format: (input: Type<T>) => Type<T>;
};
请注意,这是从您的示例中进一步修改的。您在这里有两个类型参数,但似乎只为第二个使用了默认值,所以我删除了它并使用了该默认值。但这里重要的修改是typeID
属性是泛型类型T
,而不是具体类型TypeID
。我认为您可能打算在您的代码中执行此操作,但也许很难看出区别。
现在我要从这里开始的方法是生成一个名为的类型SomeItem
,它是所有可能Item<T>
类型的联合。这种具体类型比泛型类型更容易使用:
type _SomeItem<T extends TypeID> = T extends any ? Item<T> : never;
type SomeItem = _SomeItem<TypeID>;
// type SomeItem = Item<TypeID.Number> | Item<TypeID.String> | Item<TypeID.Boolean>
这通过在 , 的定义中使用分布条件类型_SomeItem
来分布Item<T>
在值的联合中TypeID
。
最后,someFunc
可以是一个具体的函数:
const someFunc = (options: Array<SomeItem>) => {
return null as any;
};
当你使用它时,你会得到你期望的推断:
someFunc([
{
typeID: TypeID.Number,
format: input => input // has type number
},
{
typeID: TypeID.Boolean,
format: input => input // has type boolean
},
{
typeID: TypeID.String,
format: input => input // has type string
}
]);
好的,希望有帮助。祝你好运!
链接到代码
推荐阅读
- r - 如何区分R中的名字和姓氏?
- java - 用于 java 的 openapi-generator-cli 以涵盖 openapi 定义中未涵盖的未知属性
- vite - 防止 Vite 插入类似 env-var 的字符串
- java - Apache依赖错误?org.apache.parquet.hadoop.codec.SnappyCodec 未找到 Apache 库中的错误
- reactjs - react-select:防止长文本重叠
- postgresql - Postgresql: select from view multiple times?
- c++ - 从文件打印图形
- vue.js - activeTap 道具值不会改变,即使是道具也会改变
- gatsby - 更新 wordpress 帖子后盖茨比崩溃
- python - 获取 Pytorch - 张量值作为 python 中的整数