[英]Typescript union string literal in another union type
type Status = 'Active' | 'Pending' | 'Failed';
type User = {
name: string;
age: number;
status: 'active' // how to get autocomplete, it's lowercase??
} | {
error: string;
id: string;
status: 'failed' // can it be something like Status['Failed']
} |
{
id: string;
status: 'pending'
}
给定Status
作为字符串联合类型,有时需要在另一个复杂对象类型中使用该类型。 每个状态值的不同字段结构。
创建具有status
字段的User
时如何确保类型安全?
我想重用相同的类型,如下所示
const fooBarFn(status: Status) {
if (status === 'Pending') {
return {
id: '123',
status
}
}
// rest of fn
}
以上是否有任何其他模式或最佳实践?
一些解决方案
type RecordX<K extends keyof any> = {
[P in K]: P;
};
type Status = 'Active' | 'Pending' | 'Failed';
type User<T extends RecordX<Status>> = { // how to default assign
name: string;
age: number;
status: T['Active']
} | {
error: string;
id: string;
status: T['Failed']
} |
{
status: T['Pending']
}
const user: User = { // need the template type parameter
name: 'foobar';
age: 99,
status: 'NotWorking' // not working
}
如何默认第一个泛型参数,以便用户无需提供类型
您可以通过使用enum
关键字来实现这一点,如下所示:
enum Status {
ACTIVE = 'ACTIVE',
PENDING = 'PENDING',
FAILED = 'FAILED',
}
type User = {
name: string;
age: number;
status: Status.ACTIVE;
} | {
error: string;
id: string;
status: Status.FAILED;
} |
{
id: string;
status: Status.PENDING;
}
稍后您可以执行此操作来检查User
输入。
const user: User = { ... }
if (user.status === Status.PENDING) {
// Do something if status is pending
}
一种可能的方法是根据User
定义Status
,而不是反过来。 这样您就不必重复自己,也不必尝试让编译器自动完成各个状态。 它看起来像这样:
type User = {
name: string;
age: number;
status: 'Active'
} | {
error: string;
id: string;
status: 'Failed'
} | {
id: string;
status: 'Pending'
}
type Status = User['status'];
// type Status = "Active" | "Failed" | "Pending"
首先将文字Status
转换为对象格式
type Intermediate = {
Active: 'Active';
Pending: 'Pending';
Failed: 'Failed';
}
然后分配为状态的通用类型
type RecordX<K extends keyof any> = {
[P in K]: P;
};
type Status = 'Active' | 'Pending' | 'Failed';
type User<T extends RecordX<Status> = RecordX<Status>> = {
name: string;
age: number;
status: T['Active']
} | {
error: string;
id: string;
status: T['Failed']
} |
{
status: T['Pending']
}
const user: User = {
name: 'foobar';
age: 99,
status: 'Active' // autocomplete works
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.