3

I want to write the following function

function override<T, U>(first: T, second: U): T {
    let result = <T>{};
    for (let id in first) {
        result[id] = first[id];
    }
    for (let id in second) {
        result[id] = second[id];
    }
    return result;
}

but make it typesafe. In my use case, both T and U are simple records types. I want T to be required to have all the properties of U. Is there a way to express this relation?

Luka Horvat
  • 4,283
  • 3
  • 30
  • 48

2 Answers2

4

You cannot do that in a single function declaration. The reason is that extends generic constrain cannot reference other generics in the same group. However you can split the function into two parts (currying). And then use the type of the first argument (now in a separate function) to constrain the type of the second argument as shown below:

var override = <T>(first:T) => <U extends T>(second:U) : T => {
    let result = <T>{};
    for (let id in first) {
        result[id] = first[id];
    }
    for (let id in second) {
        result[id] = second[id];
    }
    return result;
}

override({a:123})({a:123, b:456}); // okay 
override({a:123})({b:456}); // error
basarat
  • 261,912
  • 58
  • 460
  • 511
  • 1
    I'm having trouble with this. I need `T extends U` instead of `U extends T` but when I write `` I get the same error. How can I say the same thing without introducing a new `T` type into the parameter list? – Luka Horvat Sep 10 '15 at 11:38
  • *another* type ... *another* parameter – basarat Sep 10 '15 at 23:47
  • If you provide a code sample of what you *expect* ... I might be able to try to tweak it `@)---` – basarat Sep 11 '15 at 14:38
  • Exactly what you wrote, but the roles of `T` and `U` in `U extends T` reversed. I want `T` to at least have the properties of `U`. – Luka Horvat Sep 11 '15 at 15:31
0

I know its an old question but currently TS supports the following syntax:

type Partial<T> = { [P in keyof T]?: T[P]; }

(Which is in lib.d.ts so you may not need to include it in your code)

So:

function override<T>(first: T, second: Partial<T>): T { ...

Yousef Salimpour
  • 694
  • 1
  • 7
  • 15