328

I have a variable.

abc:number|string;

How can I check its type? I want to do something like below:

if (abc.type === "number") {
    // do something
}

10 Answers 10

467

For :

abc:number|string;

Use the JavaScript operator typeof:

if (typeof abc === "number") {
    // do something
}

TypeScript understands typeof 🌹

This is called a typeguard.

More

For classes you would use instanceof e.g.

class Foo {}
class Bar {} 

// Later
if (fooOrBar instanceof Foo){
  // TypeScript now knows that `fooOrBar` is `Foo`
}

There are also other type guards e.g. in etc https://basarat.gitbook.io/typescript/type-system/typeguard

Sign up to request clarification or add additional context in comments.

4 Comments

Added note on instanceof even though that wasn't the asked question.
Doesn't answer the question. This doesn't get the type it confirms that it is or is not a type that you provide.
It answers the question if you look at the given context/intent of the person asking the question...
What if the type is a function. ?
80

The other answers are right, but when you're dealing with interfaces you cannot use typeof or instanceof because interfaces don't get compiled to javascript.

Instead you can use a typecast + function check typeguard to check your variable:

interface Car {
    drive(): void;
    honkTheHorn(): void;
}

interface Bike {
    drive(): void;
    ringTheBell(): void;
}

function start(vehicle: Bike | Car ) {
    vehicle.drive();

    // typecast and check if the function exists
    if ((<Bike>vehicle).ringTheBell) {
        const bike = (<Bike>vehicle);
        bike.ringTheBell();
    } else {
        const car = (<Car>vehicle);
        car.honkTheHorn();
    }
}

And this is the compiled JavaScript in ES2017:

function start(vehicle) {
    vehicle.drive();
    if (vehicle.ringTheBell) {
        const bike = vehicle;
        bike.ringTheBell();
    }
    else {
        const car = vehicle;
        car.honkTheHorn();
    }
}

3 Comments

This is a very important distinction about interfaces vs classes! I wish there was a more idiomatic way to do this, but this suggestion works well.
Question focusing on interface property types
can you do this in tsx file? React is expecting <Bike> to be an component, not a TS type.
55

I'd like to add that TypeGuards only work on strings or numbers, if you want to compare an object use instanceof

if(task.id instanceof UUID) {
  //foo
}

1 Comment

True. Worth noting that you can do this with classes but not with TypeScript interfaces or types, because they don't exist in the exported JavaScript file.
16

I suspect you can adjust your approach a little and use something along the lines of the example here:

https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates

function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

1 Comment

14

I have checked a variable if it is a boolean or not as below

console.log(isBoolean(this.myVariable));

Similarly we have

isNumber(this.myVariable);
isString(this.myvariable);

and so on.

3 Comments

worked for me, but just for knowing types!!, custom types have to use instanceof
You'll need to import util to access these functions (e.g., import { isString } from 'util';
Depricated now , use if (typeof value === 'string') instead
10

Type guards in typescript

To determine the type of a variable after a conditional statement you can use type guards. A type guard in typescript is the following:

An expression which allows you to narrow down the type of something within a conditional block.

In other words it is an expression within a conditional block from where the typescript compiler has enough information to narrow down the type. The type will be more specific within the block of the type guard because the compiler has inferred more information about the type.

Example

declare let abc: number | string;

// typeof abc === 'string' is a type guard
if (typeof abc === 'string') {
    // abc: string
    console.log('abc is a string here')
} else {
    // abc: number, only option because the previous type guard removed the option of string
    console.log('abc is a number here')
}

Besides the typeof operator there are built in type guards like instanceof, in and even your own type guards.

2 Comments

Is the part marked as quote a real quote from anywhere? If yes, from where?
Seems to come from the TypeScript Deep Dive GitBook (repo) by Basarat Ali Syed. Looks like a wonderful resource! I've been looking at the issues that turn up commonly when people start using TypeScript. This is based on the lessons from Stack Overflow / DefinitelyTyped ...
4

type of can be used for this

if (typeof abc === "number") {
    // number
} else if (typeof abc === "string"){
//string
}

Comments

1

since Typescript 4.4 you can do like bellow:

function foo(arg: unknown) {
    const argIsString = typeof arg === "string";
    if (argIsString) {
        console.log(arg.toUpperCase());
    }
}

Comments

1

Here's a way to do it if your variable's type is a union that includes multiple object interfaces that you want to decide between:

interface A {
  a: number;
}

interface B {
  b: boolean;
}

let x: string | A | B = /* ... */;

if (typeof x === 'string') {
  // x: string
} else if ('a' in x) {
  // x: A
} else if ('b' in x) {
  // x: B
}

If you want to make sure that you handled every option, you can add an exhaustiveness check. Once you've handled every option, TypeScript will notice that there are no remaining types the variable could possibly be at this point. It expresses this by giving it the never type.

If we add a final else branch that requires the variable to be the never type, we'll be proving to the type checker (and to ourselves) that this branch will never be called:

// As long as a variable never holds a type it's not supposed to,
// this function will never actually be called.
function exhaustiveCheck(param: never): never {
  throw Error('exhaustiveCheck got called somehow');
}

if (typeof x === 'string') {
  // x: string
} else if ('a' in x) {
  // x: A
} else if ('b' in x) {
  // x: B
} else {
  // x: never
  exhaustiveCheck(x);
}

If you forget to handle a case, you'll get a type error:

if (typeof x === 'string') {
  // x: string
} else if ('b' in x) {
  // x: B
} else {
  // x: A
  exhaustiveCheck(x); // TYPE ERROR: Argument of type 'A' is not
                      // assignable to parameter of type 'never'.
}

Comments

0

I have searched a lot how to check if my string variable is equal to my type and didn't found anything meaningful because any type of interface is not exist in runtime. So we need have this in runtime. There is solution that I figure out for my case.

type MyType = 'one'|'two';
function isMyType(val: string): val is MyType {
    const list:MyType[] = ['one','two'];
    return list.includes(val as MyType);
}
...
const incomingValue = 'one';
if(isMyType(incomingValue)) {
    // here typescript see incomingValue as MyType
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.