Typescript: Allow intersection type guards for multiple parameters

Created on 5 Sep 2018  路  5Comments  路  Source: microsoft/TypeScript

Search Terms

type guard multiple parameters

Suggestion

I'd like to write a type guard that takes two parameters and changes the type of both of them.

Use Cases

My specific use case is to try to make the following pattern (somewhat) more type-safe:

class Foo<TFeature, TOther> {
    // If featureCtor is null, TFeature will never be used.
    constructor(private readonly featureCtor: { new(): TFeature } | null) { }

    isFeature(thing: any): thing is TFeature {
        return !!this.featureCtor && thing instanceof this.featureCtor;
    }

    bar(thing: TFeature|TOther) {
        if (this.isFeature(thing)) {
            // Type guard should prove that this.featureCtor is not null
            new this.featureCtor();
        } else {
            // Type guard should prove this
            const x: TOther = thing;
        }
    }    
}

Examples

isFeature(thing: any, ctor: { new(): TFeature } | null): (thing is TFeature)&(ctor is { new(): TFeature }) {
    return !!this.featureCtor && thing instanceof this.featureCtor;
}

It would be even nicer to allow type guards to operate on readonly fields, so I wouldn't need to pass this.featureCtor as a parameter.

I also tried

constructor(private readonly featureCtor: TFeature extends never ? null : { new(): TFeature }) { }

But that didn't work.

Checklist

My suggestion meets these guidelines:

  • [x] This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • [x] This wouldn't change the runtime behavior of existing JavaScript code
  • [x] This could be implemented without emitting different JS based on the types of the expressions
  • [x] This isn't a runtime feature (e.g. new expression-level syntax)
Awaiting More Feedback Suggestion

Most helpful comment

Seconding a need for this:

const isValidPair = (x: null | string, y: null | string): x is string & y is null {
  return typeof x === 'string' && y === null;
};

if (isValidPair(var1, var2)) {
  // know var1 is string
  // know var2 is null
}

All 5 comments

Any news on this?

Seconding a need for this:

const isValidPair = (x: null | string, y: null | string): x is string & y is null {
  return typeof x === 'string' && y === null;
};

if (isValidPair(var1, var2)) {
  // know var1 is string
  // know var2 is null
}

This would be useful for processing overloaded function parameters where it is enough to check one parameter to assume the type of the other parameter:

function nonsense(a: number, b: number): number;
function nonsense(a: string, b: string): string;
function nonsense(a: number | string, b: number | string): number | string {
    const isNumbers = (a: number | string, b: number | string): a is number & b is number 
        => typeof a === "number";

    if (isNumbers(a, b)) {
        return a * 10 + b * 100;
    } else {
        return a.length + b.length;
    }
}

This is also convenient and meaningful for builders.

class Builder {
  private fixtureA: string | null = null
  private fixtureB: string | null = null
  // ... any other C, D, E ...
  public build() {
    if (this.ofTypeAB()) {
       return {}
    }
    if (this.ofTypeCDA()) {
       return {}
    }
  }
}

Hi, any updates?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

seanzer picture seanzer  路  3Comments

DanielRosenwasser picture DanielRosenwasser  路  3Comments

blendsdk picture blendsdk  路  3Comments

Roam-Cooper picture Roam-Cooper  路  3Comments

siddjain picture siddjain  路  3Comments