条件类型中的类型特异性
Type specificity in conditional type
我正在尝试以一种方式键入 React 组件的属性,当其中一个属性具有特定值时,另一个属性的类型 属性 会发生变化。总的来说,如果输入类型类似于 string | number
,我知道该怎么做,但如果它是 string | "specificString"
,我不知道该怎么做。也许这甚至不可能?
这是我实现该目标的两次尝试。
type Action = "createItem" | "updateItem" | "deleteItem";
type Props<TName = string> = {
name: TName;
value: TName extends "_action" ? Action : string;
};
const props: Props = {
name: "_action",
value: "wrongAction", // I want it to error
};
第二次尝试:
type Action = "createItem" | "updateItem" | "deleteItem";
type Props = {
name: "_action";
value: Action;
} | {
name: string;
value: string;
};
const props: Props = {
name: "_action",
value: "wrongAction", // I want it to error
};
有什么实现方法吗?谢谢!
看这个例子:
import React from 'react'
type Action = "createItem" | "updateItem" | "deleteItem";
type ValidateProps<T> =
/**
* Check whether our argument has allowed type shape
*/
T extends { name: infer A, value: infer V }
/**
* Check if [name] is "_action"
*/
? ('_action' extends A
/**
* If [name] is "_action" and [value] is Action
*/
? (V extends Action
/**
* Return T
*/
? T
/**
* Otherwise highlight wrong property
*/
: { name: A, value: 'Error: [value] is not allowed' })
: { name: A, value: V }
)
: never
type Props<Name, Value> = {
name: Name,
value: Value
}
const Foo = <
Name extends string,
Value extends string,
>(props: ValidateProps<Props<Name, Value>>) => <div />
const allowed1 = <Foo name="_action" value="createItem" /> // ok
const allowed2 = <Foo name="anything" value="hello" /> // ok
const not_allowed = <Foo name="_action" value="hello" /> // expected error
您需要从 name
和 value
属性 推断文字类型,然后他们对其进行验证。
如果你对参数类型推断感兴趣,可以查看我的文章here and here
P.S。请随意使用 never
而不是 'Error: [value] is not allowed'
。为了便于阅读,我添加了它
我正在尝试以一种方式键入 React 组件的属性,当其中一个属性具有特定值时,另一个属性的类型 属性 会发生变化。总的来说,如果输入类型类似于 string | number
,我知道该怎么做,但如果它是 string | "specificString"
,我不知道该怎么做。也许这甚至不可能?
这是我实现该目标的两次尝试。
type Action = "createItem" | "updateItem" | "deleteItem";
type Props<TName = string> = {
name: TName;
value: TName extends "_action" ? Action : string;
};
const props: Props = {
name: "_action",
value: "wrongAction", // I want it to error
};
第二次尝试:
type Action = "createItem" | "updateItem" | "deleteItem";
type Props = {
name: "_action";
value: Action;
} | {
name: string;
value: string;
};
const props: Props = {
name: "_action",
value: "wrongAction", // I want it to error
};
有什么实现方法吗?谢谢!
看这个例子:
import React from 'react'
type Action = "createItem" | "updateItem" | "deleteItem";
type ValidateProps<T> =
/**
* Check whether our argument has allowed type shape
*/
T extends { name: infer A, value: infer V }
/**
* Check if [name] is "_action"
*/
? ('_action' extends A
/**
* If [name] is "_action" and [value] is Action
*/
? (V extends Action
/**
* Return T
*/
? T
/**
* Otherwise highlight wrong property
*/
: { name: A, value: 'Error: [value] is not allowed' })
: { name: A, value: V }
)
: never
type Props<Name, Value> = {
name: Name,
value: Value
}
const Foo = <
Name extends string,
Value extends string,
>(props: ValidateProps<Props<Name, Value>>) => <div />
const allowed1 = <Foo name="_action" value="createItem" /> // ok
const allowed2 = <Foo name="anything" value="hello" /> // ok
const not_allowed = <Foo name="_action" value="hello" /> // expected error
您需要从 name
和 value
属性 推断文字类型,然后他们对其进行验证。
如果你对参数类型推断感兴趣,可以查看我的文章here and here
P.S。请随意使用 never
而不是 'Error: [value] is not allowed'
。为了便于阅读,我添加了它