고급 유형

횡단 유형

type Admin = {
    name: string;
    privileges: string();
};

type Employee = {
    name: string;
    startDatae: Date;
};

// 여기
type ElevatedEmlpoyee = Admin & Employee;

const e1: ElevatedEmlpoyee = {
    name: 'KIM',
    privileges: ('create-server'),
    startDatae: new Date()
}
interface Admin  {
    name: string;
    privileges: string();
};

interface Employee  {
    name: string;
    startDatae: Date;
};


interface ElevatedEmlpoyee extends Admin, Employee {}

const e1: ElevatedEmlpoyee = {
    name: 'KIM',
    privileges: ('create-server'),
    startDatae: new Date()
}

교차 유형은 인터페이스 상속과 밀접한 관련이 있습니다.

즉, 두 코드는 정확히 동일한 작업을 수행합니다.

개체 유형은 개체 속성의 조합을 나타냅니다.

type Combinable = string | number;
type Numeric = number | boolean;

type Universal = Combinable & Numeric;

숫자 유형이 유일한 교차 유형이므로 Universal은 숫자 유형으로 간주합니다.

공용체 유형은 공통점이 있는 유형을 나타냅니다.


교차 연산자는 모든 유형과 함께 사용할 수 있으므로 이와 같이 교차 유형을 쉽게 구현할 수 있습니다.

타입 가드

타입 가드의 종류

type Combinable = string | number;

function add(a: Combinable, b: Combinable) {
    // 이 조건문을 타입가드라고 함
    if (typeof a === 'string' || typeof b === 'string') {
        return a.toString() + b.toString();
    }
    return a + b;
}

위의 코드와 마찬가지로 직접 입력할 수 있습니다.

유형 가드를 사용하면 공용체 유형의 유연성을 활용하고 코드가 런타임에 올바르게 작동하는지 확인할 수 있습니다.

Typeof는 개체 유형 가드에 사용할 수 없지만 in 및 instanceof 유형 가드는 사용할 수 있습니다.

유형 보호

type Admin = {
    name: string;
    privileges: string();
};

type Employee = {
    name: string;
    startDatae: Date;
};

// 두 사용자 정의 객체 타입을 사용하여 유니언 타입을 만듬
type UnknownEmployee = Employee | Admin;

function printEmployeeInformation(emp: UnknownEmployee) {
    console.log('Name: ' + emp.name); // 에러 아님
    console.log('Privileges: ' + emp.privileges); // 에러
}

위의 코드에서 두 객체 모두 UnknownEmployee를 입력할 수 있으므로 name 속성에는 둘 다 포함되므로 버그가 아니지만 Privilege 속성에는 Admin만 포함되므로 유형 보호가 필요합니다.

typeof는 사용자 정의 객체 유형에 사용할 수 없으므로 in 키워드를 사용하여 해결할 수 있습니다.

function printEmployeeInformation(emp: UnknownEmployee) {
    console.log('Name: ' + emp.name);
    if('privileges' in emp) {
        console.log('Privileges: ' + emp.privileges);
    }
    if('startDate' in emp) {
        console.log('Start Date: ' + emp.startDate);
    }
}

유형 가디언의 인스턴스

class Car {
    drive() {
        console.log('Driving...')
    }
}

class Truck {
    drive() {
        console.log('Driving a truck...')
    }

    loadCargo(amount: number) {
        console.log('Loading cargo ...' + amount)
    }
}

type Vehicle = Car | Truck;

const v1 = new Car();
const v2 = new Truck();

function useVehicle(vehicle: Vehicle) {
    vehicle.drive();
    if (vehicle instanceof Truck) {
        vehicle.loadCargo(1000);
    }
}

문자열의 오류 검사는 typeguard에서 사용할 때 어려울 수 있으므로 instaceof를 사용하는 보다 강력한 방법도 있습니다.

instanceof는 순수한 JavaScript 함수이며 인터페이스에서 사용할 수 없습니다.

따라서 그것을 사용하면 개체가 클래스를 기반으로 하는지 확인할 수 있고 클래스를 기반으로 하는 경우 이 메서드가 있는지 확인할 수 있습니다.

친애하는 노조

interface Bird {
	// 여기
    type: 'bird';
    flyingSpeed: number;
}

interface Horse {
	// 여기
    type: 'horse';
    runningSpeed: number;
}

type Animal = Bird | Horse;

function moveAnimal(animal:Animal) {
    let speed;
    switch (animal.type) {
        case 'bird':
            speed = animal.flyingSpeed;
            break;
        case 'horse':
            speed = animal.runningSpeed;
    }
    console.log('Moving with speed: ' + speed);
}

위의 코드는 인터페이스를 통해 생성된 객체이기 때문에 타입 프로텍트를 사용할 수 없지만 복잡하고 경우가 많아질수록 실수하기 쉽습니다.

이때 각 인터페이스에 공통 속성(이 경우 type 속성)을 적용하고 case를 switch 문으로 구분하는 방법도 사용할 수 있습니다.

이 경우 In Type Guard와 달리 케이스에 자동 완성이 표시되므로 오류를 줄일 수 있습니다.

타자

index.html

...
<body>
  <input type="text" id="user-input">
</body>
...

app.ts

const userInputELement = document.getElementById('user-input');

위와 같이 코드를 작성해도 userInputElement는 HTML에서 이 입력 태그를 인식하지 못합니다.

캐스팅은 TypeScript가 직접 인식하지 못하는 특정 유형의 값을 TypeScript에 알려줌으로써 이 문제를 해결합니다.

하나는 변환하려는 요소 앞에 무언가를 추가하거나 TypeScript에 유형을 알리려는 위치에 추가하는 것입니다.

두 가지 가능성이 있습니다.

const userInputELement = <HTMLInputElement>document.getElementById('user-input')!
;

하나는 다음을 사용하여 typecasting입니다.

이와 같이 변환하려는 요소 앞에 추가하십시오.

const userInputELement = document.getElementById('user-input')!
as HTMLInputElement;

React JSX 구문과의 충돌을 피하기 위한 대안입니다.

변환하고자 하는 유형을 선택 후 키워드로 입력하면 됩니다.

선택 요소 끝에 있는 느낌표는 TypeScript에 이전 표현식이 null로 반환되지 않음을 알려줍니다.

이 느낌표 대신 다음과 같이 작성할 수 있습니다.

const userInputELement = document.getElementById('user-input');

if(userInputELement) {
    (userInputELement as HTMLInputElement).value="Hi there!
"; }

인덱스 유형

가질 수 있는 속성 측면에서 보다 유연한 개체를 만들 수 있는 기능입니다.

interface ErrorContainer {
    id: number; // 에러
    (prop: string): string;
}

정확한 프로퍼티 이름도 모르고, 얼마나 많은 프로퍼티가 있는지도 모르고, 이 인터페이스를 기반으로 하는 객체에 추가되는 프로퍼티는 문자열로 해석될 수 있는 프로퍼티 이름을 가져야 한다는 것만 알고 있습니다.

이 속성의 값도 문자열이어야 합니다.

따라서 id 속성에 숫자를 할당하면 다음과 같은 오류가 발생합니다.


interface ErrorContainer {
    (prop: string): string;
}

const errorBag: ErrorContainer = {
    email: 'Not a valid email!
', username: 'Must start with a capital character!
' }

함수 과부하

동일한 함수에 대해 여러 함수 서명을 정의하는 기능.

간단히 말해, 다른 매개변수로 함수를 호출하는 여러 가지 방법을 사용하여 함수 내에서 작업을 수행할 수 있습니다.

function add(a: Combinable, b: Combinable) {
    if (typeof a === 'string' || typeof b === 'string') {
        return a.toString() + b.toString();
    }
    return a + b;
}

const result = add('Kim', 'iltae');
result.split('') // 에러

위의 코드에서 우리는 결과가 문자열이라는 것을 알지만 TypeScript는 그렇지 않습니다.


따라서 String 메서드 Split을 사용하면 다음 오류가 발생합니다.


const result = add('Kim', 'iltae') as string;

물론 이와 같은 typecasting으로 고칠 수 있지만 더 많은 코드를 소비하고 최선이 아니므로 함수 오버로딩을 사용하는 것이 좋습니다.

function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: string, b: number): string;
function add(a: number, b: string): string;
function add(a: Combinable, b: Combinable) {
    if (typeof a === 'string' || typeof b === 'string') {
        return a.toString() + b.toString();
    }
    return a + b;
}

const result = add('Kim', 'iltae');
result.split('')

TypeScript가 반환 유형 자체를 정확하게 유추할 수 없는 경우 이러한 함수에 오버로드를 작성하여 사용할 수 있습니다.

함수가 지원할 수 있는 다양한 조합에 대해 반환되는 내용을 명확히 할 수 있습니다.

선택적 연결

이것은 개체의 속성이 설정되었는지 정의되지 않았는지 확실하지 않은 중첩 데이터로 구조화를 수행할 때 사용할 수 있습니다.

const fetchedUserData = {
    id: 'a1',
    name: 'KIM',
    job: { title: 'CEO', description: 'My own company' }
};

//                         여기  여기
console.log(fetchedUserData?.job?.title);

선택적 연결 연산자는 개체 및 개체 데이터의 중첩된 속성에 대한 안전한 액세스를 제공합니다.

물음표 앞의 요소가 정의되어 있지 않으면 그 뒤에 접근하지 않습니다.

이것은 데이터가 있는지 여부를 확인하는 if 문으로 컴파일됩니다.

제로 합체

const userInput = null;

//                           여기
const storedData = userInput ?? 'DEFAULT';

userInput이 null이거나 정의되지 않은 경우 “DEFAULT”를 할당하려고 함을 의미합니다.

아래 코드와 달리 이 프로세스는 다음과 같은 userInput의 잘못된 값이 아닌 null 및 정의되지 않은 값만 처리합니다.

0 또는 빈 문자열(”).

const userInput = null;

const storedData = userInput || 'DEFAULT';