[英]Conditional types in TypeScript
我想知道我是否可以在 TypeScript 中使用条件类型?
目前我有以下界面:
interface ValidationResult {
isValid: boolean;
errorText?: string;
}
但我想删除errorText
,并且仅在isValid
为false
作为必需属性时才使用它。
我希望我能够将其编写为以下界面:
interface ValidationResult {
isValid: true;
}
interface ValidationResult {
isValid: false;
errorText: string;
}
但如你所知,这是不可能的。 那么,您对这种情况有何看法?
对这种逻辑建模的一种方法是使用联合类型,像这样
interface Valid {
isValid: true
}
interface Invalid {
isValid: false
errorText: string
}
type ValidationResult = Valid | Invalid
const validate = (n: number): ValidationResult => {
return n === 4 ? { isValid: true } : { isValid: false, errorText: "num is not 4" }
}
然后编译器能够根据布尔标志缩小类型
const getErrorTextIfPresent = (r: ValidationResult): string | null => {
return r.isValid ? null : r.errorText
}
为避免创建仅用于创建第三个接口的多个接口,您也可以直接交替使用type
:
type ValidationResult = {
isValid: false;
errorText: string;
} | {
isValid: true;
};
错误所展示的联合是我推荐的处理方式。 尽管如此,Typescript确实有一些称为“ 条件类型”的东西,他们可以处理这个问题。
type ValidationResult<IsValid extends boolean = boolean> = (IsValid extends true
? { isValid: IsValid; }
: { isValid: IsValid; errorText: string; }
);
declare const validation: ValidationResult;
if (!validation.isValid) {
validation.errorText;
}
这个ValidationResult
(实际上是ValidationResult<boolean>
由于默认参数)相当于在 bugs 的答案或CertainPerformance 的答案中产生的联合,并且可以以相同的方式使用。
这里的优点是您还可以传递已知的ValidationResult<false>
值,然后您就不必测试isValid
因为它会被认为是false
并且errorString
会被知道存在。 对于这种情况,可能没有必要——条件类型可能很复杂且难以调试,因此可能不应不必要地使用它们。 但是你可以,而且这似乎值得一提。
这是一种不需要 isValid 属性的替代方法。 相反,我们可以使用 errortext 属性的存在或不errortext
作为标记。 下面是一个例子:
// Empty for now, can always add properties to it
interface Valid{}
interface InValid {
errorText: string;
}
// sum/union type, the type is either Valid OR InValid
type ValidationResult = Valid | InValid;
// custom type guard to determine the type of the result
// TS uses this function to narrow down the type to eiter valid or invalid
function checkIfValidResult(result: ValidationResult): result is InValid{
return result.hasOwnProperty('errorText') ? true : false;
}
// example of using the type guard
function doSomethingWithResult(result: ValidationResult) {
if (checkIfValidResult(result)) {
throw new Error(result.errorText);
} else {
console.log('Success!');
}
}
doSomethingWithResult({});
// logs: Success
doSomethingWithResult({errorText:'Oops something went wrong'});
// Throws error: Oops something went wrong
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.