0

I have this type.

type Deposit {
    num1: number;
    num2: number;
}

type Nice {
   num: number;
   deposit: Deposit;
}

Now, I use Nice, but I need to somehow extend it and I want its deposit to be including more fields. In the end, like this:

type Deposit {
    num1: number;
    num2: number;
    num3: string;
    num4: string;
}

type Nice {
   num: number;
   deposit: Deposit;
}

But, I can't change Deposit or Nice types since they come from the library.

1
  • What does since they come from the library. mean? Commented May 26, 2021 at 7:58

2 Answers 2

2

You can create a custom child type using the extends keyword and just place it in a common types.ts file, then import the type from there instead of importing it from the library directly.

// src/types.ts

import { Deposit as DepositBase, Nice as NiceBase } from 'some-lib';

export interface Deposit extends DepositBase {
  num3: string;
  num4: string;
}

export interface Nice extends NiceBase {
  deposit: Deposit;
}

Then, to use it:

// src/some-lib-wrapper.ts

import * as someLib from 'some-lib';
import { Deposit, Nice } from './types'; // our extended types

// you can "re-type" the library functions in this wrapper module
// to use our custom extended types
export function makeDeposit(nice: Nice): Deposit {
  /* call someLib.makeDeposit here... */
}
// src/index.ts

import { makeDeposit } from './some-lib-wrapper'; // use the wrapped version
                                                  // with our extended types
import { Deposit, Nice } from './types';

// use your custom wrapped functions & types
makeDeposit(...);
Sign up to request clarification or add additional context in comments.

4 Comments

Presuming this "library" exposes these types for a reason this doesn't seem like a great idea.
it exposes these types , yes. Why is it not a good idea ?
Assuming Nika is just adding some additional meta information, this is a perfectly normal use-case. Another potential approach would be to wrap the library's type and add your "extended" properties as extra keys, something like interface DepositExtended { deposit: Deposit; extra: { num3: string; num4: string } }, but I think as long as the extended types are purely additive (they're not removing/overwriting library types with more strict types) it should be safe to use extends as shown above.
Because @NikaKurashvili you could simply make breaking changes to the types, thus making your library not work.
1

You can use helper type for extending existing property:

type Deposit = {
    num1: number;
    num2: number;
}

type Nice = {
    num: number;
    deposit: Deposit;
}

type ExtendProp<Obj, Prop, NewValue> = {
    [P in keyof Obj]: P extends Prop ? Obj[P] & NewValue : Obj[P]
}

type Result = ExtendProp<Nice, 'deposit', { foo: 'bar' }> // { deposit: Deposit & { foo: 'bar';  };

Playground

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.