带有从未输入字段的打字稿界面
Typescript interface with never typed fields
给定以下接口,什么是有效的可分配值?
interface A {
x: number,
y: never
}
我所期望的是 const a: A = { x: 1 }
会起作用,但它错误地指出字段 y
是必需的。一旦我把 y
放在那里,它就说该值不可分配给 never
.
我的实际用例是这样的:
interface Context<T extends MyRequest> {
id: string;
token: T extends AuthenticateRequest ? string : never;
}
interface AuthenticatedRequest extends MyRequest { ... }
这里我无法为 Context<MyRequest>
创建值,因为它说缺少 token
。
我目前的解决方法是:
type Context<T extends MyRequest> = {
id: string;
} & (T extends AuthenticatedRequest ? {
token: string;
} : {})
但由于显而易见的原因,这看起来很难看...
知道我如何正确地做到这一点吗?
您需要将类型设置为字符串或未定义。当永远不会为变量赋值时使用 never
类型,更多关于 here.
我认为这种方法应该可以解决您的问题。
interface A {
x: number,
y: string | undefined
}
Type never
是空类型的表示。这是什么意思 - 没有属于这种类型的值,这意味着如果你使用它总是编译错误。
你需要的是更高级别的条件类型,考虑:
type Context<T extends MyRequest> = T extends AuthenticateRequest ? {
id: string;
token: string;
} : { id: string };
这种方法消除了为 token
设置 undefined
的负担。如果需要token
,那么对于T extends AuthenticateRequest
它是一个字符串,如果不是,则token
字段不存在。
根据@Titian Cernicova-Dragomir 和@Maciej Sikora 提到的要点,解决方法是我需要的类型定义的正确方法。 interface
不能有类型为 never
的字段,因为无法为其分配有效值,从而使接口无用。
这是我最终用于代码的内容:
type Context<T extends MyRequest> = Readonly<
{
logger: MyLogger;
timestamp?: number;
} & (T extends AuthenticatedRequest
? {
token: Token;
user: string;
}
: {}) &
(T extends GameRequest
? {
gameId: string;
}
: {}) &
(T extends ETagRequest
? {
etag: string;
}
: {}) &
(T extends UnParameterizedRequest
? {}
: {
params: Record<string, string | undefined>;
})
>;
给定以下接口,什么是有效的可分配值?
interface A {
x: number,
y: never
}
我所期望的是 const a: A = { x: 1 }
会起作用,但它错误地指出字段 y
是必需的。一旦我把 y
放在那里,它就说该值不可分配给 never
.
我的实际用例是这样的:
interface Context<T extends MyRequest> {
id: string;
token: T extends AuthenticateRequest ? string : never;
}
interface AuthenticatedRequest extends MyRequest { ... }
这里我无法为 Context<MyRequest>
创建值,因为它说缺少 token
。
我目前的解决方法是:
type Context<T extends MyRequest> = {
id: string;
} & (T extends AuthenticatedRequest ? {
token: string;
} : {})
但由于显而易见的原因,这看起来很难看...
知道我如何正确地做到这一点吗?
您需要将类型设置为字符串或未定义。当永远不会为变量赋值时使用 never
类型,更多关于 here.
我认为这种方法应该可以解决您的问题。
interface A {
x: number,
y: string | undefined
}
Type never
是空类型的表示。这是什么意思 - 没有属于这种类型的值,这意味着如果你使用它总是编译错误。
你需要的是更高级别的条件类型,考虑:
type Context<T extends MyRequest> = T extends AuthenticateRequest ? {
id: string;
token: string;
} : { id: string };
这种方法消除了为 token
设置 undefined
的负担。如果需要token
,那么对于T extends AuthenticateRequest
它是一个字符串,如果不是,则token
字段不存在。
根据@Titian Cernicova-Dragomir 和@Maciej Sikora 提到的要点,解决方法是我需要的类型定义的正确方法。 interface
不能有类型为 never
的字段,因为无法为其分配有效值,从而使接口无用。
这是我最终用于代码的内容:
type Context<T extends MyRequest> = Readonly<
{
logger: MyLogger;
timestamp?: number;
} & (T extends AuthenticatedRequest
? {
token: Token;
user: string;
}
: {}) &
(T extends GameRequest
? {
gameId: string;
}
: {}) &
(T extends ETagRequest
? {
etag: string;
}
: {}) &
(T extends UnParameterizedRequest
? {}
: {
params: Record<string, string | undefined>;
})
>;