如何在接口中声明一个可选的泛型类型?
How to declare an optional generic type in an interface?
我有这个界面:
export interface AlertInteraction<T> {
id: AlertId;
data: T;
buttonId: AlertButtonId;
}
但也有不需要数据的时候。我知道我可以将其声明为 data: T
但我想知道我是否可以这样:
export interface AlertInteraction<T> {
id: AlertId;
data: T;
buttonId: AlertButtonId;
}
export interface AlertInteraction {
id: AlertId;
buttonId: AlertButtonId;
}
所以,如果我给出 T
那么我假设我想要访问数据,如果没有则假设它不存在。可能吗?
你可以试试这个
export interface AlertInteraction<T = any> {
id: AlertId;
data?: T;
buttonId: AlertButtonId;
}
// those are valid:
const x: AlertInteraction = {id: 'AlertId', buttonId: 'AlertButtonId'};
// Accept the data property as number only.
const x: AlertInteraction<number> = {id: 'AlertId', buttonId: 'AlertButtonId', data: 123};
或者您可以使它们成为 2 个接口,一个没有 data
属性 和通用参数,第二个扩展第一个并具有数据 属性 和通用参数
像这样
export interface AlertInteractionBase {
id: string;
buttonId: string;
}
export interface AlertInteraction<T> extends AlertInteractionBase {
data: T;
}
创建第二个包装类型,当它被提供一个类型时它不会省略数据,但是当没有提供类型时,数据字段被省略。
正如您所说,将数据设置为可选是不正确的,因为您需要该字段在您不需要时根本不存在。
export interface IInterationData<T> {
id: AlertId;
data: T;
buttonId: AlertButtonId;
}
type IAlertInteraction<T = undefined> = T extends undefined
? Omit<IInterationData<any>, "data">
: IInterationData<T>;
export const a: IAlertInteraction = {
id: 1,
buttonId: ""
};
export const b: IAlertInteraction<number> = {
id: 1,
data: 2,
buttonId: ""
};
为了实现这一点,我们需要使用条件类型。
type AlertId = string; // just example type alias
type AlertButtonId = string; // just example type alias
type AlertInteraction<T = undefined> = {
id: AlertId;
buttonId: AlertButtonId;
} & (T extends undefined ? {} : {
data: T;
})
// example usage
// no need for data (T is undefined)
const a: AlertInteraction = {
id: '1',
buttonId: '1'
}
// data prop is required
const b: AlertInteraction<number> = {
id: '1',
data: 1,
buttonId: '1'
}
最重要的是这部分:
& (T extends undefined ? {} : {
data: T;
})
如果 T 可分配给未定义,我们有条件地加入或类型 {}
,或者我们加入 {data: T}
其他类型。结果,如果我们不设置泛型,它默认为 undefined
并且我们的类型构造函数计算为:
// For T == undefined
{
id: AlertId;
buttonId: AlertButtonId;
} & {}
// what is equal to just:
{
id: AlertId;
buttonId: AlertButtonId;
}
如果参数(泛型)被提供为与 undefined
不同的东西,那么最终类型的形式为:
// For T != undefined
{
id: AlertId;
buttonId: AlertButtonId;
} & { data: T}
// which is equal to
{
id: AlertId;
buttonId: AlertButtonId;
data: T;
}
其中 T
是由类型构造函数的参数给出的类型。还要清除信息 - 类型构造函数 = 任何带有泛型参数的类型定义。
我有这个界面:
export interface AlertInteraction<T> {
id: AlertId;
data: T;
buttonId: AlertButtonId;
}
但也有不需要数据的时候。我知道我可以将其声明为 data: T
但我想知道我是否可以这样:
export interface AlertInteraction<T> {
id: AlertId;
data: T;
buttonId: AlertButtonId;
}
export interface AlertInteraction {
id: AlertId;
buttonId: AlertButtonId;
}
所以,如果我给出 T
那么我假设我想要访问数据,如果没有则假设它不存在。可能吗?
你可以试试这个
export interface AlertInteraction<T = any> {
id: AlertId;
data?: T;
buttonId: AlertButtonId;
}
// those are valid:
const x: AlertInteraction = {id: 'AlertId', buttonId: 'AlertButtonId'};
// Accept the data property as number only.
const x: AlertInteraction<number> = {id: 'AlertId', buttonId: 'AlertButtonId', data: 123};
或者您可以使它们成为 2 个接口,一个没有 data
属性 和通用参数,第二个扩展第一个并具有数据 属性 和通用参数
像这样
export interface AlertInteractionBase {
id: string;
buttonId: string;
}
export interface AlertInteraction<T> extends AlertInteractionBase {
data: T;
}
创建第二个包装类型,当它被提供一个类型时它不会省略数据,但是当没有提供类型时,数据字段被省略。
正如您所说,将数据设置为可选是不正确的,因为您需要该字段在您不需要时根本不存在。
export interface IInterationData<T> {
id: AlertId;
data: T;
buttonId: AlertButtonId;
}
type IAlertInteraction<T = undefined> = T extends undefined
? Omit<IInterationData<any>, "data">
: IInterationData<T>;
export const a: IAlertInteraction = {
id: 1,
buttonId: ""
};
export const b: IAlertInteraction<number> = {
id: 1,
data: 2,
buttonId: ""
};
为了实现这一点,我们需要使用条件类型。
type AlertId = string; // just example type alias
type AlertButtonId = string; // just example type alias
type AlertInteraction<T = undefined> = {
id: AlertId;
buttonId: AlertButtonId;
} & (T extends undefined ? {} : {
data: T;
})
// example usage
// no need for data (T is undefined)
const a: AlertInteraction = {
id: '1',
buttonId: '1'
}
// data prop is required
const b: AlertInteraction<number> = {
id: '1',
data: 1,
buttonId: '1'
}
最重要的是这部分:
& (T extends undefined ? {} : {
data: T;
})
如果 T 可分配给未定义,我们有条件地加入或类型 {}
,或者我们加入 {data: T}
其他类型。结果,如果我们不设置泛型,它默认为 undefined
并且我们的类型构造函数计算为:
// For T == undefined
{
id: AlertId;
buttonId: AlertButtonId;
} & {}
// what is equal to just:
{
id: AlertId;
buttonId: AlertButtonId;
}
如果参数(泛型)被提供为与 undefined
不同的东西,那么最终类型的形式为:
// For T != undefined
{
id: AlertId;
buttonId: AlertButtonId;
} & { data: T}
// which is equal to
{
id: AlertId;
buttonId: AlertButtonId;
data: T;
}
其中 T
是由类型构造函数的参数给出的类型。还要清除信息 - 类型构造函数 = 任何带有泛型参数的类型定义。