Xatyrian
Xatyrian

Reputation: 1384

In Typescript, Declare an interface and define it in different files

I am building a software that uses WebSocket with the package NodeJS ws. I organised my networking around a module that is charged of receiving and sending the messages. Because i am using TypeScript, I want to use the type checking which can be pretty handy sometimes. So I constructed two types:

// networking.ts
export class Message {
    constructor(
        public request: string,
        public params: Params) {}
}

export interface Params {
    messageId?: number;
}

This works fine as long as I am only required to use messageId as a parameter. But what if I need to also send a nickname as a parameter ? I could add it to the Params definition but I don't want the networking engine to bother to know all the different parameters that can be sent (you can imagine that I have actually more than one parameter to send)...

Is there a way to do something like:

// profile-params.ts
export interface Params {
    nickname:string;
}

// admin-params.ts
export interface Params {
    authorizations: string[];
}

Such that in the end, the declaration of Params can be merged ? I looked at the official documentation but it can't make it work on different files.

Thanks

Upvotes: 2

Views: 203

Answers (3)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249756

@Daniel W Strimpel is ok, if your interface does not come from a module and you are ok with putting it in the global scope.

If you want the interface to be part of a module you could use module augmentation to extend the interface:

//pModule.ts
export interface Params {
    messageId: number;
}

//pAug.ts
import { Params } from "./pModule";
declare module './pModule' {
    interface Params {
        nickname: string;
    }
}
//usage.ts
import {Params} from './pModule'
import './pAug'

let p : Params = {
    nickname: '',
    messageId: 0
}

Upvotes: 2

Daniel W Strimpel
Daniel W Strimpel

Reputation: 8470

I don't fully know the reasons why right now (other than the fact that the moment something is exported it is turned into a module), but the only way I know how to accomplish this is to have them in their own individual files where nothing is exported and import the files (without the { Params } from syntax).

// ./message/params.model.ts
interface Params {
    messageId?: number;
}

// ./user/params.model.ts
interface Params {
    nickname: string;
}

// ./authorization/params.model.ts
interface Params {
    authorizations: string[];
}

// ./some.component.ts
import './message/params.model.ts';
import './user/params.model.ts';
import './authorization/params.model.ts';

const params: Params = {
    authorizations: ['black-belt', 'secret-service'],
    nickname: 'ninja',
    messageId: 1
};

Upvotes: 0

unional
unional

Reputation: 15589

Use generics:

export class Message<P extends Params> {
  constructor(
    public request: string,
    public params: P
  ) { }
}

export interface Params {
  messageId?: number
}

// profile-params.ts
export interface ProfileParams extends Params {
  nickname: string
}

const message = new Message<ProfileParams>('', { nickname: 'a' })

Upvotes: 0

Related Questions