Skip to content

Tips and Tricks

How to tell if an object conforms to a Typescript interface?

ts
const isTSInterface = <T>(
  value: any,
  keys: (keyof T)[],
  requiredKeys: (keyof T)[]
): value is T => {
  if (typeof value !== 'object' || value === null) return false;

  return (
    requiredKeys.every((key) => key in value) && //  Ensure all required keys are present
    (Object.keys(value) as (keyof T)[]).every((key) => keys.includes(key)) //  Ensure no undefined keys are present
  );
};

ts
interface Cat {
  name: string;
  color: 'tabby' | 'calico' | 'black' | 'white' | 'bald';
  kittens?: number;
}

const invalidCat = {
  name: 'Nyako',
  color: 'white',
  ownerName: 'Power',
};

const properCat = {
  name: 'Chomosuke',
  color: 'black',
};

console.log(
  isTSInterface<Cat>(
    invalidCat,
    ['name', 'color', 'kittens'],
    ['name', 'color']
  )
); // returns false

console.log(
  isTSInterface<Cat>(properCat, ['name', 'color', 'kittens'], ['name', 'color'])
); // returns true

Source: Medium: Follow-up: How to tell if an object conforms to a Typescript interface? from Tamás Polgár

Check variable against custom type

You can write a user-defined type guard

ts
// Initial type
type Fruit = 'apple' | 'banana' | 'grape';

// Declare an array and use TypeScript inference
const fruit = ['apple', 'banana', 'grape'] as const;
type Fruit = (typeof fruit)[number];

// Use a type guard function
const isFruit = (x: any): x is Fruit => fruit.includes(x);

// This function will narrow the type of the variable passed, and only accept the type Fruit
let myfruit = 'pear';

// Usage
if (isFruit(myfruit)) {
  console.log(`${myfruit} is a fruit`);
} else {
  console.log(`${myfruit} is not a fruit`);
}

TypeScript has two kind of module types declaration

"local" (normal modules) and ambient (global)