Best practice for exporting types from declaration file to external project

5.4k views Asked by At

I have a working solution to - export types defined from declaration file, that can be used within my project and to be exported out to external projects.

The only way I could make this work was using a namespace to wrap the type.

github - Project X

@types/index.d.ts

declare namespace projectGlobal {
  interface Person = {
    name: string;
    age: number;
  }
}
// other localised types here, cannot be exported...
interface Local {
  func: () => string
}

src/index.ts

export type Person = ProjectGlobal.Person; // can only export if referenced via namespace.
// export type Local = Local; // This fails to export

const person1: Person = {
  name: 'john',
  age: 45
}

github Project Y

import {Person} from 'projectx';

const person1: Person = {
  name: 'john',
  age: 45
}

While I'm happy to settle for this as a solution I want to know if this is the right way to do this or if there is a best practice for this.

1

There are 1 answers

4
Alex Chashin On BEST ANSWER

Declaration files are not supposed to be used like that. Usually you don't write them at all, actually. The main reasons when you want to write them are:

  1. When you have a library in JavaScript and you want TypeScript users to be able to use it as well. You could rewrite your library in TypeScript, but this is not fun, so you can just write declarations and leave the code in JavaScript.

  2. Sometimes if you want to declare some global things. Like for example, in React projects you can import data from image files .png, .jpg and co. So React creates a .d.ts file with declarations for them (because by default TS doesn't consider these files to be modules):

declare module '*.jpg' {
  const url: string
  export default url
}

That's pretty much it, in other cases just use normal .ts files:

export type Person = {
  name: string
  age: number
}

const person1: Person = {
  // ...
}

I don't see any reason, why you can't do that, if you have one, feel free to comment. If you just want separation between types and logic, create types.ts and do-stuff.ts and just use index.ts to reexport stuff:

// types.ts
export type Person = {
  name: string
  age: number
}
// do-stuff.ts
import { Person } from './types'

const person1: Person = {
  // ...
}
export default person1
// index.ts
export * from './types'
export { default } from './do-stuff'
// you can write this line just in case you will want to export something
// with a named export
export * from './do-stuff'