TypeScript
Inference
As Keyword

As Keyword

Using the as keyword, you can 'force' typescript to treat a variable as a specific type. This is useful when you know that a variable is of a certain type, but typescript cant infer it.

Basics

In following implementation, typedAnimal function returns a Dog | Cat type. However, we know that the return type is Cat because we are passing a cat: Cat object to the function. In this case, we can use the as keyword to force typescript to treat the return type as typeof cat which in this example is Cat.

as.ts
type Dog = {
  name: string;
  age: number;
};
 
const dog: Dog = {
  name: "dog",
  age: 10,
};
 
type Cat = {
  name: string;
  age: number;
  isEvil: boolean;
};
 
const cat: Cat = {
  name: "cat",
  age: 10,
  isEvil: true,
};
 
type Animal = Dog | Cat;
 
function typedAnimal(animal: Animal) {
  if ("isEvil" in animal) {
    return animal;
  }
  return animal;
}
 
const animal = typedAnimal(cat) as typeof cat;
// animal: Cat

However, this is not ideal to cast the return type using as each time, instead we can use generics to infer the return type.

genericsInsteadOfAs.ts
type Animal = Dog | Cat;
 
function typedAnimal<T extends Animal>(animal: T): T {
  if ("isEvil" in animal) {
    return animal;
  }
  return animal;
}
 
const animal = typedAnimal(cat);
// animal: Cat
️🚫

In most cases you should avoid using as keyword, and instead use generics to infer the type, or use other stratiegies to narrow down the type instead of simply telling typescript to treat the value as a specific type.

Not compatible types

Sometimes we want to cast some value to a type that is not compatible with the value. Consider the following example:

notCompatible.ts
type Horse = {
  name: string;
  isFast: boolean;
};
 
const animal = typedAnimal(dog) as Horse;
// Conversion of type 'Dog' to type 'Horse' may be a mistake because neither type sufficiently overlaps with the other.
// If this was intentional, convert the expression to 'unknown' first.
// Property 'isFast' is missing in type 'Dog' but required in type 'Horse'.

Lets look at another example: we have a fumction, that expect certain type, but we want to pass a different type to it because we know, that the function will work with it.

notCompatible2.ts
type Dog = {
  name: string;
  age: number;
};
 
const dog: Dog = {
  name: "dog",
  age: 10,
};
 
type Horse = {
  name: string;
  isFast: boolean;
};
 
function typedAnimal(animal: Horse) {
  return animal.name;
}
 
const animal = typedAnimal(dog as Horse);
// Conversion of type 'Dog' to type 'Horse' may be a mistake because neither type sufficiently overlaps with the other.
// If this was intentional, convert the expression to 'unknown' first.
// Property 'isFast' is missing in type 'Dog' but required in type 'Horse'.

We got the same error, but we know that what we want to return from the function is just animal.name which is property that both Dog and Horse have. In this case, we can use unknown type to cast the value to it, and then to the type we want.

notCompatible3.ts
const animal = typedAnimal(dog as unknown as Horse);
// no error
️🚫

Using as unknown as is not a good practice, and should be avoided, as its simply disconnecting typescript from the value, and telling it to treat it as a different type no matter what.