Skip to content

Instantly share code, notes, and snippets.

@OliverJAsh

OliverJAsh/foo.md

Last active Sep 19, 2019
Embed
What would you like to do?
TypeScript excess property checks: caveats and workarounds

TypeScript excess property checks: caveats and workarounds

https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks

Not checked when spreading

type MyObject = {
  foo: string;
  bar: string;
  baz: string;
};
type MyOtherObject = {
  foo: string;
};

declare const myObject: MyObject;

// Omit + rest
// Oops, we forgot to omit a prop (`baz`).
const { bar, ...restProps } = myObject;
const myOtherObject: MyOtherObject = {
  // No excess error :-(
  ...restProps
};

This is particularly problematic when spreading props into a React component, as it can hurt performance or create invalid HTML: https://github.com/microsoft/TypeScript/issues/31798.

Workarounds

Instead of using "omit + rest" (above), "pick":

// Pick
const myOtherObject: MyOtherObject = {
  foo: myObject.foo,
  // Excess error :-)
  baz: myObject.baz
};

Not checked on empty object literals

type A = {};
const a: A = { a: 1 };

https://stackoverflow.com/questions/42537727/empty-interface-allow-any-object

Not checked on function return types

type Fn = () => {
  foo: string;
};
const fn: Fn = () => ({
  foo: "foo",
  // No excess error :-(
  bar: "bar"
});

https://github.com/microsoft/TypeScript/issues/33507

Workarounds

Annotate function return type or use constructor

type FnResult = {
  foo: string;
};
type Fn = () => FnResult;
const fn: Fn = (): FnResult => ({
  foo: "foo",
  // Excess error :-)
  bar: "bar"
});

Not checked in unions, beware of runtime exceptions

The future

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.