スキップしてメイン コンテンツに移動

[TypeScript] How to use "type"

Intro

When I write codes, I often confuse if I should use type alias or interface.
Actually, they are quite similar in some situations.

So I want to know how to distinct them.

Environments

  • TypeScript ver.3.8.3
  • Node.js ver.12.10.0

Similarity

After compiling

Both type alias and interface are only in TypeScript.
After compiling to JavaScript, they will be disappeared.

TypeScript


interface ISample{
    name: string;
}
type TSample = {
    message: string
};
function main() {
    const iSample: ISample = {
        name: 'Hello'
    };
    const tSample: TSample = {
        message: 'World'
    };
}
main();

JavaScript


"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function main() {
    var iSample = {
        name: 'Hello'
    };
    var tSample = {
        message: 'World'
    };
}
main();

Treat as same type

If an object has same properties with them, they treat as their type, though the object doesn't implement them explicitly.

function main() {
    const iSample = {
        name: 'Hello'
    };
    const iSample2: ISample = iSample; // OK
    
    const tSample = {
        message: 'World'
    };
    const tSample2: TSample = tSample; // OK
}

Class implemmentation

Class can implement them.

/** OK */
class IClassSample implements ISample {
    public name: string = 'Hello'
}
/** OK */
class TClassSample implements TSample {
    public message: string = 'World'
}

Difference

Declaration merging

Interface has "declaration merging".
If there are some interfaces what have same name in same namespace, same file, and etc, they will be merged.

interface ISample{
    name: string;
}
interface ISample{
    message: string;
}
function main() {
    // 1st and 2nd ISample are merged.
    const iSample: ISample = {
        name: 'Hello',
        message: 'World'
    };
}

Extends

Only interface can extends type alias and interface.

interface ISample{
    name: string;
}
type TSample = {
    message: string
};
interface IExtendSample extends ISample, TSample {
    id: number;
}
function main() {
    const iSample: IExtendSample = {
        id: 0,
        name: 'Hello',
        message: 'World'
    };
}

But type alias can Cross type to get similar result.

interface ISample{
    name: string;
}
type TSample = {
    message: string
};
type TCrossSample = ISample & TSample & { id: number; }
function main() {
    const tSample: TCrossSample = {
        id: 0,
        name: 'Hello',
        message: 'World'
    };
}

Declare type

Interface is only declared in this way.

interface InterfaceName {
    propertyName: Type
};

But type alias can be declared in many kinds of type.


interface ISample{
    name: string;
}
type TSample = {
    message: string
};
/** Union type */
type TUnionSample = ISample|TSample;
/** Cross type */
type TCrossSample = ISample & TSample & { id: number; }
/** Tuple */
type TTupleSample = [string, number];
/** Function */
type TFunctionSample = (message: string) => void;
/** Object */
type TObjectSample = {
    message: string
};
/** Mapped type */
type TBase = {
    id: number,
    name: string
};
type TMappedSample = { [P in keyof TBase]: string; };
/** Conditional type */
type TConditionalSample<T> = T extends string? 'string': 'other';
function main() {
    const crossSample: TCrossSample = {
        id: 0,
        name: 'Hello',
        message: 'World'
    };
    const tupleSample: TTupleSample = ['hello', 0];
    const mappedSample: TMappedSample = {
        id: '0',
        name: 'Hello'
    };
    const conditionalSample: TConditionalSample<string> = 'string';
}

Inteface also can create some types like type alias.
For example, interface can create function type like item12 of "Effective TypeScript".

interface IFunctionSample {
    (message: string): void
}
type TFunctionSample = (message: string) => void;

const callIFunction: IFunctionSample = (message) => console.log(message);
const callTFunction: TFunctionSample = (message) => console.log(message);

function main() {
    callIFunction('Hello'); // OK
    callTFunction('World'); // OK
}

But the others that are like Union type etc. cannot.

When should I use "type"?

When I can use either, should I use type alias?
According to "Effective TypeScript", I should follow the project style.
And if I need to publish to other projects, I should choose interface.

When the project is for a web application, if the object is for detecting behaviour and implemented by class, I want to choose interface.
If the object is for saving some data like data transfer object, I want to choose type alias.
Maybe this is because I get used to write C# codes :)

References

TypeScript/spec.md at master · microsoft/TypeScript · GitHub
Advanced Types · TypeScript
Effective TypeScript
Interface vs Type alias in TypeScript 2.7 - Martin Hochel - Medium
TypeScript: Interfaces vs Types - Stack Overflow

コメント

このブログの人気の投稿

[Nest.js] Show static files

Intro I wanted to use Nest.js and WebRTC(node-webrtc). NestJS - A progressive Node.js framework Documentation | NestJS - A progressive Node.js framework And because I wanted to try with simple page(not use JavaScript frameworks), I added static HTML, CSS, JavaScript into a Nest.js project. Prepare Install First, I installed @nestjs/cli. First steps | NestJS - A progressive Node.js framework As same as last time , I couldn't do global install because I had used Volta. But I could installed by volta. volta install @nestjs/cli Create project nest new nest-web-rtc-sample volta pin node@12 Run npm start After doing "npm start", I could getting "Hello World!" from http://localhost:3000. Add static files I could add static files by two ways. @nestjs/serve-static First one of them was using "serve-static". Serve Static | NestJS - A progressive Node.js framework npm install --save @nestjs/serve-static And I needed adding a module into app.modu

[Angular][ASP.NET Core] Upload chunked files

Intro I wanted to send files to Web application (made by ASP.NET Core). If the file size had been small, I didn't need do any special things. But when I tried to send a large file, the error was occurred by ASP.NET Core's limitation. Though I could change the settings, but I didn't want to do that, because I hadn't known the file sizes what would been actually using. So I splitted the data into chunks first, and sent them. After receiving all chunks, I merged them into one file. There might be some libraries or APIs (ex. Stream API) what did them automatically, but I couldn't find them. What I did [ASP.NET Core] Make CORS enabled [Angular] Split a large file into chunks [Angular][ASP.NET Core] Send and receive data as form data [ASP.NET Core] Merge chunks into one file [ASP.NET Core] Make CORS enabled Because the client side application(Angular) and the server side application(ASP.NET Core) had been separated, I had to make CORS(Cross-Origin Requests)

[Nest.js] Use WebSocket with ws

Intro Until last time , I had used node-web-rtc to try WebRTC. But because the example was a little complicated for I understood the core functions of using WebRTC. So I look for other frameworks or libraries. PeerJS is a famous library for WebRTC. peers/peerjs: Peer-to-peer data in the browser. - GitHub peers/peerjs-server: Server for PeerJS - GitHub PeerJS - Simple peer-to-peer with WebRTC A problem is I don't know how to integrate to the Nest.js project. I couldn't find examples. So I don't choose at least this time. What shall I choose? According MDN, WebRTC doesn't specify strictly what technology is used on server application for connecting two devices. Signaling and video calling - Web APIs | MDN But in many examples include MDN's one use WebSocket. samples-server/s/webrtc-from-chat at master · mdn/samples-server · GitHub So I try WebSocket in the Nest.js project. Use WebSocket in a Nest.js project Nest.js has a function for using We