エレガントなタイプのスクリプトの概要

65376 ワード

🤔 タイプスクリプトの使用方法


1.作成者とユーザー


タイプシステム

  • コンパイラが使用するタイプを指定するシステム
  • コンパイラ自動推定タイプのシステム
  • タイプスクリプトのタイプシステム


  • タイプを明確に指定できます.

  • タイプが明示的に指定されていない場合、タイプスクリプトコンパイラは自動的にタイプを推定します.

    タイプは変数が何ができるかを決定します.
  • 関数の使い方を誤解するJavaScript

    // JavaScript
    
    // f2 실행의 결과가 NaN을 의도한 것이 아니라면
    // 이 함수의 작성자는 매개변수 a 가 number 타입이라는 가정으로 함수를 작성했습니다.
    function f2(a) {
    	return a;
    }
    
    // 사용자는 사용법을 숙지하지 않은 채, 문자열을 사용하여 함수를 실행했습니다.
    console.log(f2(10)); // 380
    console.log(f2('Mark')); // NaN
    noImplicitAny 옵션
    タイプが明確に指定されていない場合、タイプスクリプトが推定時にanyと判断すると、コンパイルエラーが発生し、タイプを明確に指定するように起動します.strictNullChecks 옵션すべてのタイプに自動的に含まれるnullとundefinedを削除します.noImplicitReturns 옵션関数内のすべてのコードが値を返さない場合、コンパイルエラーが発生します.

    object literal type

    function f7(a:{name:string; age: number}):string {
    	return `이름은 ${a.name}이고 연령대는 ${Math.floor(a.age/10) * 10}대 입니다.`;
    }
    
    console.log(f7({name:'Mark',age:38})); // 이름은 Mark이고, 연령대는 30대 입니다.
    console.log(f7('Mark')); // error TS2345: Argument of type 'string' is not assignable to parameter of type '{name:string; age:number;}'.

    2.インタフェースとタイプ別名


    構造タイプsystem-構造が同じ場合は同じタイプ

    interface IPerson{
    	name: string;
    	age: number;
    	speak(): string;
    }
    
    type PersonType = {
    	name: string;
    	age: number;
    	speak(): string;
    };
    
    let personInterface: IPerson = {} as any;
    let personType: PersonType = {} as any;
    
    personInterface = personType;
    personType = personInterface;

    nominaltype system-構造は同じですが名前が異なるタイプ

    type PersonID = string & { readonly brand: unique symbol};
    
    function PersonID(id:string):PersonID{
    	return id as PersonID;
    }
    
    function getPersonById(id:PersonID){}
    
    getPersonById(PersonID('id-aaaaaa'));
    getPersonById('id-aaaaaa'); // error TS2345: Argument of type 'string' is not assignable to 
    // parameter of type 'PersonID'. Type 'string' is not assignable to type '{readonly brand:unique symbol;}'.

    Function

    // type alias
    type EatType = (food:string) => void;
    
    // interface
    interface IEat {
    	(food:string): void;
    }

    Array

    // type alias
    type PersonList = string[];
    
    // interface
    interface IPersonList{
    	[index:number]:string;
    }

    Intersection

    interface ErrorHandling {
    	success:boolean;
    	error?:{ message: string };
    }
    
    interface ArtistsData {
    	artists: { name: string }[];
    }
    
    // type alias
    type ArtistsResponseType = Artists & ErrorHandling {}
    
    // interface
    interface IArtistsResponse extends ArtistsData, ErrorHandling{}
    
    let art : ArtistsResponseType;
    let iar : IArtistsResponse;

    Union Types

    interface Bird {
    	fly(): void;
    	layEggs(): void;
    }
    
    interface Fish {
    	swim(): void;
    	layEggs():void;
    }
    
    type PetType = Bird | Fish;
    
    interface IPet extends PetType {} // error TS2312: An interface can only extend an object type or 
    //intersection of object types with statically known members;
    
    class Pet implements PetType {} // error TS2422: A class can only implement an object type or 
    //intersection of object types with statically known members

    Declation Merging - interface

    interface MergingInterface {
    	a: string;
    }
    
    interface MergingInterface {
    	b: string;
    }
    
    let mi: MergingInterface = { a: 'hello', b: 'world' };
    他のモジュール/ライブラリタイプを拡張する場合はglobalを選択します.d.ts作成後のネームスペースでの使用

    [delay type aliasとinterfaceはいつ使いますか?]

  • タイプ別名:別名、結合タイプ、交差タイプ
  • インタフェース:新しいタイプ
  • を作成

    3.サブタイプとスーパータイプ


    Case 1

    let sub1: 1 = 1;
    let sup1: number = sub1;
    sub1 = sup1; // error Type 'number' is not assignable to type '1';
    
    let sub2: number[] = [1];
    let sup2: object = sub2;
    sub2 = sup2; // error Type 'number[]' is not assignable to type '{number,number}'
    
    let sub3: [number,number] = [1,2];
    let sup3: number[] = sub3;
    sub3 = sup3; // error Type 'number[]' is not assignable to type '[number,number]'.
    // Target requires 2 element(s) but source may have lower.

    Case 2

    let sub4: number = 1;
    let sup4: any = sub4;
    sub4 = sup4;
    
    let sub5: never = 0 as never;
    let sup5: number = sub5;
    sub5 = sup5; // error Type 'number' is not assignable to type 'never'
    
    class SubAnimal {}
    class SubDog extends SubAnimal{
    	eat(){}
    }
    
    let sub6: SubDog = new SubDog();
    let sup6: SubAnimal = sub6;
    sub6 = sup6; // error Property 'eat' is missing type 'SubAnimal' but required in type 'SubDog'.

    ≪共通関係|Common Relationships|emdw≫:同じタイプまたはサブタイプの場合、割当てできます。

    // primitive type
    let sub7: string = '';
    let sup7: string | number = sub7;
    
    // object - 각각의 프로퍼티가 대응하는 프로퍼티와 같거나 서브타입이어야 한다.
    let sub8 : { a: string; b: number } = { a: '', b: 1 };
    let sup8 : { a: string | number; b : number } = sub8;
    
    // array - object와 마찬가지
    let sub9 : Array<{ a: string; b: number }> = [{a: '', b: 1 }];
    let sup9 : Array<{ a: string | number ; b: number }> = sub9;

    ハーフボトル:関数のパラメータタイプが同じかスーパータイプの場合、割り当てることができます。

    class Person {}
    class Developer extends Person {
    	coding() {}
    }
    class StartupDeveloper extends Developer{
    	burning() {}
    }
    
    function tellme(f: (d: Developer)=> Developer) {}
    
    // Developer 에다가 Developer 할당하는 경우
    tellme(function dToD(d:Devleopr):Developer {
    	return new Developer();
    });
    
    // Developer 에다가 Person 할당하는 경우
    tellme(function pToD(d:Person):Developer{
    	return new Developer();
    });
    
    // Developer 에다가 StartupDeveloper 할당하는 경우 (타입에러는 나지 않지만 기대하는 결과X)
    tellme(function sToD(d:StartupDeveloper):Developer {
    	return new Developer();
    });
    strictFunctionTypes 옵션関数のパラメータタイプが同じかスーパータイプでない場合は、エラーによって警告されます.

    unknown代替

    // 입력은 마음대로, 
    // 함수 구현은 문제 없도록
    function funknown(a: unknown): number | string | void {
    	a.toString(); // error! Object is of type 'unknown'
    	
    	// 명확하게 타입별로 처리하도록 유도 
    	if(typeof a === 'number'){
    		return a * 38;
    	}else if(typeof a === 'string'){
    		return `Hello ${a}`;
    	}
    }

    4.理解型推論

    let a = 'Mark'; // string
    const b = 'Mark'; // 'Mark' => literal type
    
    let c = 38; // number
    const d = 38; // 38 => literal type
    
    let e = false; // boolean
    const f = false; // false => literal type
    
    let g = ['Mark', 'Haeun']; // string[]
    const h = ['Mark','Haeun']; // string[]
    
    const f = ['Mark','Haeun'] as const; // readonly ['Mark','Haeun']

    Best common type

    let j = [0,1,null]; // (number|null)[]
    const k = [0,1,null]; // (number|null)[]
    
    class Animal{}
    class Rhino extends Animal{}
    class Elephant extends Animal{}
    class Snake extends Animal{}
    
    let i = [new Rhino(),new Elephant(),new Snake()]; // (Rhino | Elephant|Snake)
    const m = [new Rhino(),new Elephant(),new Snake()]; // (Rhino | Elephant|Snake)
    
    const n = [new Animal(),new Rhino(),new Elephant(),new Snake()]; // Animal[]
    const o: Animal[] = [new Rhino(),new Elephant(),new Snake()]; // Animal[]

    Context Type-位置による推定

    // Parameter 'e' implicitly has an 'any' type.
    const click = (e) => {
    	e; // any
    };
    
    document.addEventListener('click',click);
    document.addEventListener('click',(e)=>{
    	e; // MouseEvent
    });

    5.タイプGuardを使用してセキュリティを決定


    Type of Type Guard-通常はPrimitiveタイプ

    function getNumber(value: number | string):number{
    	value; // number | string
    	if(typeof value === 'number'){
    		value; // number
    		return value;
    	}
    	value; // string
    	return -1;
    }

    instanceof Type Guard

    interface IMachine {
    	name: string;
    }
    
    class Car implements IMachine {
    	name: string;
    	wheel: number;
    }
    
    class Boar implements IMachine {
    	name: string;
    	motor: number;
    }
    
    function getWhellOrMotor(machine: Car | Boat): number{
    	if(machine instanceof Car){
    		return machine.wheel; // Car
    	}else {
    		return machine.motor; // Boat
    	}
    }

    Instanceof Type Guard-Errorは、オブジェクトの区別によく使用されます。

    class NegativeNumberError extends Error {}
    
    function getNumber(value: number): number | NegativeNumberError {
    	if(value < 0) return new NegativeNumberError();
    	return value;
    }
    
    function main(){
    	const num = getNumber(-10);
    
    	if(num instanceof NegativeNumberError){
    		return;
    	}
    
    	num; // number
    }

    処理in operatorタイプGuard-objectのproperty有無

    interface Admin {
    	id: string;
    	role: string;
    }
    
    interface User {
    	id: string;
    	email: string;
    }
    
    function redirect(user: Admin | User) {
    	if("role" in user){
    		routeToAdminPage(user.role);
    	}else{
    		routeToHomePate(user.email);
    	}
    }

    literal Type Guard-objectのプロパティは同じで、タイプが違います

    interface IMachine {
    	type: string;
    }
    
    class Car implements IMachine {
    	type: 'CAR';
    	wheel: number;
    }
    
    class Boat implements IMachine {
    	type: 'BOAT';
    	motor: number;
    }
    
    function getWheelorMotor(machine: Car | Boat): number {
    	if(machine.type === 'CAR'){
    		return machine.wheel;
    	}else {
    		return machine.motor;
    	}
    }

    custom Type Guard

    function getWheelOrMotor(machine:any):number{
    	if(isCar(machine)){
    		return machine.wheel;
    	}else if(isBoat(machine)){
    		return machine.motor;
    	}else{
    		return -1;
    	}
    }
    
    function isCar(arg:any):arg is Car {
    	return arg.type === 'CAR';
    }
    
    function isBoat(arg:any):arg is Boat {
    	return arg.type === 'BOAT';
    }

    6.安全にクラスを作成する


    カテゴリ属性のタイプを明確に指定する必要があります

    class Square {
    	area: number;
    	sideLength: number;
    }
    
    const square = new Square();
    console.log(square.area); // compile time - number, runtime - undefined
    console.log(square.sideLength); // complie time - number, runtime - undefined
    strictPropertyInitialization 옵션classのpropertyがジェネレータまたは宣言に値を指定していない場合、コンパイルエラーが発生し、注意を喚起します.

    宣言でClass Propertyを初期化

    class Square {
    	area: number = 0;
    	sideLength: number = 0;
    }

    クラスプロパティジェネレータで初期化

    class Square {
    	area: number;
    	sideLength: number;
    
    	constructor(sideLength: number){
    		this.sideLength = sideLength;
    		this.area = sideLength ** 2;
    	}
    }

    クラス属性のタイプ推論

    // 생성자에 의해 property 타입이 추론됨
    class Square {
    	area;
    	sideLength;
    	
    	constructor(sideLength: number){
    		this.sideLength = sideLength;
    		this.area = sideLength ** 2;
    	}
    }
    まだ生成者を離れては推論できない
    class Square {
    	sideLength!: number; // !로 의도를 표현해야 한다.
    	
    	constructor(sideLength: number){
    		this.initialize(sideLength);
    	}
    
    	initialize(sideLength: number){
    		this.sideLength = sideLength;
    	}
    
    	get area(){
    		return this.sideLength ** 2;
    	}
    }