question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow intersection type guards for multiple parameters

See original GitHub issue

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:

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

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:74
  • Comments:9

github_iconTop GitHub Comments

57reactions
CharlesStovercommented, Nov 19, 2019

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
}
33reactions
m5rcommented, Jul 27, 2020

Hi, any updates?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can I write a type guard that asserts multiple invariants?
Of course, it's not necessary to use that operator, the type intersection operator, in this case because we can simplify it to
Read more >
Handbook - Unions and Intersection Types - TypeScript
An intersection type combines multiple types into one. This allows you to add together existing types to get a single type that has...
Read more >
Advanced TypeScript Types Cheat Sheet (with Examples)
An intersection type is a way of combining multiple types into one. This means that you can merge a given type A with...
Read more >
How to use type guards in TypeScript - LogRocket Blog
A type guard is a TypeScript technique used to get information about the type of a variable, usually within a conditional block.
Read more >
How To Do Anything in TypeScript With Type Guards
Type guards are conditional checks that allow types to be narrowed from general types to more specific ones. With type guards, we do ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found