Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

TypeScript const assertion: Avoid type widening inside function

I have the following object with a const assertion:

const foo = {
  bar: ['a', 'b'],
} as const;

My goal is to write a function that updates the bar array and correctly infers the new type.

I can achieve the intended result when I pass foo.bar into the function:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

type Bar = Readonly<string[]>;

function update<T extends Bar>(arr: T) {
  return {
    bar: [...arr, 'c'],
  } as const;
}

const updatedFoo = update(foo.bar);

// Inferred type is as expected:
//
// const updatedFoo: {
//  readonly bar: readonly ["a", "b", "c"];
// }

But I cannot get this to work when I pass in foo itself:

type Foo = Readonly<{ bar: Bar }>;

function update2<T extends Foo>(obj: T) {
  return {
    bar: [...obj.bar, 'c'],
  } as const;
}

const updatedFoo2 = update2(foo);

// Inferred type is too wide:
//
// const updatedFoo2: {
//   readonly bar: readonly [...string[], "c"];
// }

How can I rewrite update2 to correctly infer the type of bar as readonly ["a", "b", "c"]?

>Solution :

The simplest solution would probably to continue using T to represent the type of bar. We can give the parameter obj an object type having a property bar of type T.

function update2<T extends Bar>(obj: { bar: T }) {
  return {
    bar: [...obj.bar, 'c'],
  } as const;
}

const updatedFoo2 = update2(foo);

// const updatedFoo2: {
//     readonly bar: readonly ["a", "b", "c"];
// }

If you want to use the whole obj type as T, you will have to use a type assertion.

function update2<T extends Foo>(obj: T) {
  return {
    bar: [...obj.bar as T["bar"], 'c'],
  } as const;
}

Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading