[英]How to pass type as a function parameter
I have the below types checking code to verify if userInput is one of the defined value我有以下类型检查代码来验证 userInput 是否是定义的值之一
const variantColorValues = ['primary', 'black', 'green', 'red', 'white'] as const;
export type VariantColor = (typeof variantColorValues)[number];
function isOfTypeVariantColor(selectedColor: string): selectedColor is VariantColor {
return (variantColorValues as readonly string[]).includes(selectedColor);
}
isOfTypeVariantColor('red') //true
isOfTypeVariantColor('purple') //false
The code above works great.上面的代码效果很好。 However the code will bulk up if I implement same logic to other properties too, so I thought of turning isOfTypeVariantColor
into a generic function.然而,如果我对其他属性也实现相同的逻辑,代码会变大,所以我isOfTypeVariantColor
变成一个通用函数。
function isOfType(userInput: string, valueList: string[]): userInput is VariantColor {
return (valueList as readonly string[]).includes(userInput);
}
And my problem now is that I'm not sure how to turn userInput is VariantColor
where VariantColor
becoming a parameter我现在的问题是我不确定如何将userInput is VariantColor
,其中VariantColor
成为参数
You could use this:你可以用这个:
// Make sure to make valueList readonly so you can use readonly arrays like variantColorValues
function isOfType<T, U extends T>(userInput: T, valueList: readonly U[]): userInput is U {
return (valueList as readonly T[]).includes(userInput);
}
const string: string = 'red';
if (isOfType(string, variantColorValues)) {
string; // VariantColor
}
const number: number = 0
if (isOfType(number, [1, 2, 3] as const)) {
number; // 1 | 2 | 3
}
T
is the user input type and you are checking if userInput
is type U
. T
是用户输入类型,您正在检查userInput
是否为U
类型。 For example, when using isOfType
with variantColorValues
, T
would be string
and U
would be VariantColor
.例如,当使用isOfType
和variantColorValues
, T
将是string
, U
将是VariantColor
。
Edit: Per Gerrit0's comment, you don't actually need two type parameters:编辑:根据 Gerrit0 的评论,您实际上并不需要两个类型参数:
function isOfType2<T>(userInput: unknown, valueList: readonly T[]): userInput is T {
return (value as readonly unknown[]).includes(userInput);
}
However, it won't pick up on this:但是,它不会注意到这一点:
if (isOfType(number, variantColorValues)) {}
// ~~~~~~~~~~~~~~~~~~
// Argument of type 'readonly ["primary", "black", "green", "red", "white"]' is not assignable to parameter of type 'readonly number[]'.
// Type 'string' is not assignable to type 'number'.
if (isOfType2(number, variantColorValues)) {
number; // never
}
Here's how I've done it:这是我如何做到的:
const variantColorValues = ['primary', 'black', 'green', 'red', 'white'] as const;
export type VariantColor = (typeof variantColorValues)[number];
const variantRoleValues = ["teacher", "student"] as const;
export type VariantRole = (typeof variantRoleValues)[number];
// This possibly isn't needed, it could be just strings, but I think it's good to explicitly narrow the types.
type PossibleVariants = VariantColor | VariantRole
function isOfType<T extends PossibleVariants>(value: string, arrayOfPossibleValues: readonly T[]) : value is T {
return (arrayOfPossibleValues as readonly string[]).includes(value);
}
Demo of use:使用演示:
const t1 = "teacher"; // In this scenario typescript knows this is the narrowest type "teacher"
if (isOfType(t1, variantColorValues)){ // No error, this is what we want right?
if (t1 === 'red') { //t1 is of type never, it's annoying that this doesn't give you an error.
//see: https://github.com/microsoft/TypeScript/issues/28982
}
}
const t2 = "teacher" as VariantRole; // For demo purposes, lets say we don't know if this is "teacher" or "student"
if (isOfType(t2, variantColorValues)){ // No error, this is what we want right?
if (t2 === 'red') { // t2 is of type never
}
const t3 = "teacher" as string; // For demo purposes, we don't know what kind of string this is.
if (isOfType(t3, variantColorValues)){ // No error, this is what we want right?
if (t3 === 'red') { // t3 is of type "red" |"black" ...
if (t3 === 'student') { // expected error: This condition will always return 'false' since the types '"primary" | "black" | "green" | "red" | "white"' and '"student"' have no overlap.(2367)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.