简体   繁体   中英

How to define a generic Type Guard in Typescript?

I want to define an interface for my classes that contains a isValidConfig function to be used as type guard. But I am not sure how to declare it.

I have done this:

type AnyConfig = ConfigA | ConfigB | ConfigC;

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

and

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

But I always get errors in the implementation like:

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 '.

Is it possible to do this? I haven't found the way.

The error is because you can't have have a guard that enforce against a generic. Following from the official TS docs: https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

You can do something like this to guard against an individual type:


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;
}


It's worth adding that types must be enforced at compile time because TypeScript simply cannot perform run-time checks (by then it's already been transpiled to JavaScript, which performs dynamic (run-time) checking). In other words, you can only guard against a specific known type.

If you want to check that a given expected config IS a config, then continuing from the example above, you can do:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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