'How to override type properties in TypeScript

For example, I have

type Line = {
  start: Point;
  end: Point;
  color: string; //'cyan'/'aquablue'/...
}

But now I want to create new line type on the base of Line, so that it stores color as number:

type HexColorLine = Point & {
  color: number;
}

Now I expect the HexColorPoint type be equal to

{
  start: Point;
  end: Point;
  color: number;
}

But it equals to

{
  start: Point;
  end: Point;
  color: string | number;
}

Is there a way to override but not extend the prop type with some short syntax? Do i really have to define entirely new type for this?



Solution 1:[1]

Create a helper type:

type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;

Usage:

type HexColorLine = Overwrite<Line, { color: number }>

Solution 2:[2]

This is not supported at the moment. TypeScript would need a concept of subtraction types. Proposals exist https://github.com/Microsoft/TypeScript/issues/12215 and https://github.com/Microsoft/TypeScript/issues/4183

Fix

Create a base type :

type LineBase = {
  start: Point;
  end: Point;
}
type LineBase = LineBase & {
  color: string; //'cyan'/'aquablue'/...
}

Solution 3:[3]

TL;DR:

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
type Override<T, U> = Omit<T, keyof U> & U

type ColorNumber =  {
  color: number;
}

type HexColorPoint = Override<
  Line,
  ColorNumber
> // --> {start: Point; end: Point; color: number}

I assume you wanted to do

type HexColorLine = Line & {
  color: number;
}

instead of

type HexColorLine = Point /* <-- typo? */ & {
  color: number;
}

With Typescript >2.8 i was able to override like this:

From https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html :

We did not include the Omit type because it is trivially written as Pick<T, Exclude<keyof T, K>>.

// So we define Omit -.-
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>

// Sidenote: 
// keyof is just getting all the keys for a given type separeted by |
// keyof Line --> 'start' | 'end' | 'color'

// And we define Override which unions the type without unwanted keys and the 
// type defining the new keys
type Override<T, U> = Omit<T, keyof U> & U

// just define which properties you want to redefine 
// and remove "Point &" as it will be done in the Override type
type HexColorLine =  {
  color: number;
}
type HexColorPoint = Override<
  Line,
  HexColorLine
> // --> {start: Point; end: Point; color: number}

Solution 4:[4]

A simple one off solution as of TypeScript 3.5 could be:

type HexColorLine = Omit<Line, 'color'> & {
  color: number;
}

Solution 5:[5]

You can try Override from the utility-types package https://github.com/piotrwitek/utility-types#overwritet-u. So in the future maybe you would like to use other cool helpers from there.

Solution 6:[6]

To expand on Pablo's answer which uses Omit, you can do the following to make a more generic utility type.

type Overwrite<Base, Overrides> = Omit<Base, keyof Overrides> & Overrides


type HexColorLine = Overwrite<Line, { color: number }>

This omits all of the keys in the provided Overrides type from the Base type, then combines that with the provided Overrides.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Maxim Mazurok
Solution 2 basarat
Solution 3 farukg
Solution 4 Pablo R. Dinella
Solution 5
Solution 6 joshfarrant