我需要创建一个接口,该接口可以是字符串,也可以是具有三个键之一的对象。
基本上我有一个函数,根据错误返回一些信息:
export const determineError = (error: ServerAlerts): AlertError => {
if (typeof error !== "string") {
if (error.hasOwnProperty("non_field_errors")) {
return error.non_field_errors[0];
} else if (error.hasOwnProperty("detail")) {
return error.detail;
} else if (error.hasOwnProperty("email")) {
return error.email[0];
} else {
return UNKNOWN_ERROR;
}
} else {
return error;
}
};
以下是这些类型:
export type AlertError =
| "Unable to log in with provided credentials."
| "E-mail is not verified."
| "Password reset e-mail has been sent."
| "Verification e-mail sent."
| "A user is already registered with this e-mail address."
| "Facebook Log In is cancelled."
| string;
export interface ServerAlerts {
non_field_errors: [string];
detail: string;
email: [string];
}
但是我在这里设计ServerAlerts
的方法对我来说不起作用,因为ServerAlerts也可以是string
,并且如果它具有其密钥之一,则只能具有一个。
您将如何设计这种类型或接口?
编辑:我尝试通过给键打个问号来使键成为可选键,但随后我的棉绒布在determineError
中的相应键的错误返回语句中抱怨。
答案 0 :(得分:2)
如果我对您的理解正确,只需将参数声明为ServerAlerts
或string
:
export const determineError = (error: ServerAlerts|string): AlertError => {
// -----------------------------------------------^^^^^^^
在评论中,您说过ServerAlerts
这三个属性都是可选的,因此您需要使用?
对其进行标记:
interface ServerAlerts {
non_field_errors?: [string];
detail?: string;
email?: [string];
}
但是,这意味着键入object
的任何内容也将起作用,因为所有字段都是可选的。因此,如果您同时执行上述两项操作,则会得到:
determineError("foo"); // Works
determineError({ non_field_errors: ["x"] }); // Works
determineError({ detail: "x" }); // Works
determineError({ email: ["x"] }); // Works
determineError({}); // Works (because all fields are optional)
let nonLiteralServerAlerts: object;
nonLiteralServerAlerts = { foo: ["x"] };
determineError(nonLiteralServerAlerts); // Works (because all fields are optional)
determineError({ foo: ["x"] }); // Fails (correctly)
建议您仅在参数签名中使用object
。如果您要需要这三个字段之一(我相信可以取消该UNKNOWN_ERROR
分支),则可以定义三个接口,并ServerAlerts
组成一个他们:
interface ServerAlertsNonFieldErrors {
non_field_errors: [string];
}
interface ServerAlertsDetail {
detail: string;
}
interface ServerAlertsEmail {
email: [string];
}
type ServerAlerts = ServerAlertsNonFieldErrors | ServerAlertsDetail | ServerAlertsEmail;
然后您将在返回特定字段时使用类型断言:
if (error.hasOwnProperty("non_field_errors")) {
return (error as ServerAlertsNonFieldErrors).non_field_errors[0];
// ------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果这样做,您将得到:
determineError("foo"); // Works
determineError({ non_field_errors: ["x"] }); // Works
determineError({ detail: "x" }); // Works
determineError({ email: ["x"] }); // Works
determineError({}); // Fails (correctly)
let nonLiteralServerAlerts: object;
nonLiteralServerAlerts = { foo: ["x"] };
determineError(nonLiteralServerAlerts); // Fails (correctly)
determineError({ foo: ["x"] }); // Fails (correctly)