在下面的代码中,如果我没有在每个动作中都使用'as'关键字指定kind,则方法的推断类型会将其扩展为任何Kind类型。有办法避免将“ Kind.PAYPAL重复为Kind.PAYPAL”吗?
enum Kind {
CASH = 'CASH',
PAYPAL = 'PAYPAL',
CREDIT = 'CREDIT'
}
const Cash = () => ({
kind: Kind.CASH as Kind.CASH,
});
const PayPal = (email: string) => ({
kind: Kind.PAYPAL as Kind.PAYPAL,
email
});
const CreditCard = (payload: { cardNumber: string, cvv: string }) => ({
kind: Kind.CREDIT as Kind.CREDIT,
payload
});
type PaymentMethod = ReturnType<
typeof Cash
| typeof PayPal
| typeof CreditCard
>;
function describePaymentMethod(method: PaymentMethod): string {
switch (method.kind) {
case Kind.CASH:
// Here, method has type Cash
return "Cash";
case Kind.PAYPAL:
// Here, method has type PayPal
return `PayPal (${method.email})`;
case Kind.CREDIT:
// Here, method has type CreditCard
return `Credit card (${method.payload.cardNumber})`;
}
}
答案 0 :(得分:1)
假设您使用的是TypeScript 3.4或更高版本,则可以按以下方式使用const
assertions
const Cash = () => ({
kind: Kind.CASH as const
});
const PayPal = (email: string) => ({
kind: Kind.PAYPAL as const,
email
});
const CreditCard = (payload: { cardNumber: string; cvv: string }) => ({
kind: Kind.CREDIT as const,
payload
});
将kind
属性的类型解释得尽可能狭窄:
在TS3.4之前,或者在您不想使用const
断言的情况下,您必须依靠TypeScript的heuristics for determining when and when not to widen literals,例如以下帮助函数:
const lit = <T extends string | number | boolean | void | null | {}>(x: T) => x;
,如果可能的话,它返回x
作为字符串/数字/布尔文字,因为类型T
受包括string
,number
和{{ 1}}。然后您将像这样使用它:
boolean
任何一种方法都可以为您工作。希望能有所帮助。祝你好运!