30

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?

Eugene Beliaev
  • 781
  • 1
  • 8
  • 15
  • 3
    I'm fairly sure you can't override like you are trying to do. You could instead declare a `SimpleLine` without the color property, and then declare `Line` and `HexColorLine` as extending the `SimpleLine`? Is there some reason I'm missing that you can't do this? – Gerrit0 Mar 28 '17 at 22:02
  • See also: [Overriding interface property type defined in Typescript d.ts file](https://stackoverflow.com/questions/41285211/overriding-interface-property-type-defined-in-typescript-d-ts-file) and [Exclude property from type](https://stackoverflow.com/questions/48215950/exclude-property-from-type) – MarcusOtter Aug 11 '22 at 01:58

7 Answers7

65

Create a helper type:

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

Usage:

type HexColorLine = Overwrite<Line, { color: number }>
Maxim Mazurok
  • 3,856
  • 2
  • 22
  • 37
Karol Majewski
  • 23,596
  • 8
  • 44
  • 53
17

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

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

In TypeScript 3.5 or later you can use Omit<Type, Keys>.

For types:

type HexColorPoint = Omit<Line, "color"> & {
    color: number;
}

For interfaces:

interface HexColorPoint extends Omit<Line, "color"> {
    color: number;
}
MarcusOtter
  • 1,095
  • 10
  • 19
7

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.

joshfarrant
  • 1,089
  • 1
  • 14
  • 27
5

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'/...
}
basarat
  • 261,912
  • 58
  • 460
  • 511
  • Thanks, this helped! I had type where I needed to narrow the type on a property and this works. – Robula Jul 11 '18 at 09:20
4

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}
farukg
  • 523
  • 4
  • 12
2

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.