繁体   English   中英

TypeScript 中的条件类型

[英]Conditional types in TypeScript

我想知道我是否可以在 TypeScript 中使用条件类型?

目前我有以下界面:

interface ValidationResult {
  isValid: boolean;
  errorText?: string;
}

但我想删除errorText ,并且仅在isValidfalse作为必需属性时才使用它。

我希望我能够将其编写为以下界面:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM