首页 > 解决方案 > 如何在 Typescript 中定义通用类型保护?

问题描述

我想为我的类定义一个接口,其中包含一个isValidConfig用作类型保护的函数。但我不确定如何声明它。

我已经这样做了:

type AnyConfig = ConfigA | ConfigB | ConfigC;

public abstract isValidConfig<T extends AnyConfig>(config: AnyConfig): config is T;

  public abstract isValidConfig<T = AnyConfig>(config: T): config is T;

但是我总是在实现中遇到错误,例如:

public isValidConfig<T extends ConfigA >(config: T): config is T {
    return config.type === TrainingTypes.A;
} /// Types of parameters 'config' and 'config' are incompatible.
      Type 'T' is not assignable to type 'ConfigA '.

是否有可能做到这一点?我还没找到路。

标签: angulartypescript

解决方案


错误是因为你不能有一个针对泛型强制执行的警卫。遵循官方 TS 文档:https ://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

您可以执行以下操作来防范单个类型:


enum ConfigTypes {
  a = 'a',
  b = 'b',
  c = 'c'
}

interface ConfigA {
  field: number;
  type: ConfigTypes.a;
}

interface ConfigB {
  otherField: string;
  type: ConfigTypes.b;
}

interface ConfigC {
  yetAnotherField: string[];
  type: ConfigTypes.c;
}

type AnyConfig = ConfigA | ConfigB | ConfigC;

export function isValidConfigA(config: AnyConfig): config is ConfigA {
  return config.type === ConfigTypes.a;
}


值得补充的是,必须在编译时强制执行类型,因为 TypeScript 根本无法执行运行时检查(到那时它已经被转译为执行动态(运行时)检查的 JavaScript)。换句话说,您只能防范特定的已知类型。

如果您想检查给定的预期配置是否是配置,然后从上面的示例继续,您可以执行以下操作:

export function isValidConfig(config: AnyConfig): config is AnyConfig {
  return (
    config.type === ConfigTypes.a ||
    config.type === ConfigTypes.b ||
    config.type === ConfigTypes.c
  );
}

推荐阅读