undefined
undefined

Reputation: 6884

Typescript merge interfaces from multiple files

I have a file named service.ts which exposes the following code:

export interface SomeInterface {
  keyOne: string;
}

export class TestService<T = SomeInterface> {
  property: T;
}

In index.ts file I am using the service:

import { TestService } from './service';

const service = new TestService();
service.property.keyOne

I also created index.d.ts file which declare the same interface SomeInterface with more keys:

export interface SomeInterface {
  keyTwo: number;
}

The problem is that service.property only "knows" the keyOne property. How can I tell typescript to merge both of them?

https://stackblitz.com/edit/typescript-cp8zmv

Upvotes: 6

Views: 7943

Answers (2)

ford04
ford04

Reputation: 74750

If I understand you correctly (your comment in @chris p bacon's answer), you want to augment a module type definition from a library. The link to declaration merging in TypeScript docs is already a good catch. There are some good answers out there dealing with third party lib type extensions: here and here.

For your example, if we want to augment a library module type definition for some reason (let's say vendor-lib.d.ts instead of your index.d.ts to make it clearer), we can do that via Module Augmentation:

vendor-lib.d.ts:

export interface SomeInterface {
  keyTwo: number
}

service.ts

// here for simplicity a relative import
import { SomeInterface } from "./vendor-lib"

// Augment above imported module. 
// Important: this file must be a module (not a script) via `import/export`.
// Then augmentation will work. Otherwise compiler expects a module declaration.
declare module "./vendor-lib" {
  interface SomeInterface {
    keyOne: string
  }
}

index.ts:

const service = new TestService(); service.property = {...};
service.property.keyOne // works
service.property.keyTwo // works

StackBlitz

Upvotes: 13

baao
baao

Reputation: 73271

You'd extend the interface and give it another name

export interface SomeInterface {
  keyOne: string;
}

export interface SomeExtendingInterface extends SomeInterface {
  keyTwo: number;
}

Or merge them to a type that has both properties

interface Foo {
    foo: string;
}

interface Bar {
    bar: string;
}

type Baz = Foo & Bar;

const foo: Baz = {
    foo: '',
    bar: ''
};

Upvotes: 3

Related Questions