컴파일러는 필수요소 프로퍼티의 유무, 프로퍼티 타입을 검사한다.
?, readonly예약어로 프로퍼티를 컨트롤할 수 있다.
1. ?: 반드시 속하는 프로퍼티가 아니면서 사용 가능함을 알려주기 위해 사용d
interface Circle {
radius: number;
color?: string;
}
const circle: Circle = { radius: 10 } // not error
2.Readonly: 객체가 처음 생성될 때만 값 설정이 가능하고, 이후 수정이 불가능함
interface Point {
readonly x: number;
readonly y: number;
}
const point: Point = { x: 10, y: 10 }
point.x = 20; // error
let arr: Array<number> = [1, 2, 3, 4];
let readonly_arr: ReadonlyArray<number> = arr;
readonly_arr[0] = 12; // error
readonly_arr.push(5); // error
interface IArea {
(width: number, height: number): number;
}
// 아래 함수에서 w: number, h: number이다.
function calArea: IArea = (w, h) => {
return w * h;
// return 'hello' => error
}
// 배열의 경우 아래처럼 이용할 수 있다.
interface Person {
[index: number]: string;
}
let people: Person = ["rabbit", "cheshire", "queen"];
interface shapeInterface {
getArea(): number;
}
interface triangleInterface extends shapeInterface {
width: number;
height: number;
}
interface circleInterface extends shapeInterface {
radius: number;
}
// this를 사용하기 위해선 내부에 width와 height를 명시해줘야 하지만 public으로 인자를 받으면 생략할 수 있다.
class triangle implements triangleInterface {
constructor(public width: number, public height: number) {
this.width = width;
this.height = height;
}
getArea() {
return (this.width * this.height) / 2;
}
}
// parameter를 public으로 선언하면 this를 이용한 값 초기화를 생략할 수 있다.
class circle implements circleInterface {
constructor(public radius: number) {}
getArea() {
return Math.PI * Math.pow(this.radius, 2);
}
}
class Queue<T> {
protected data: Array<T> = [];
push(item: T): void {
this.data.push(item);
}
pop(): T | undefined {
return this.data.shift();
}
}
const numberQueue = new Queue<number>();
numberQueue.push(0);
numberQueue.push('1'); // error 사전 검출 가능
numberQueue.push(+'1'); // 위에서 인지한 error를 수정, 단항 더하기를 이용해 type을 변경하는 것이다.
|
를 사용해 두 개 이상의 타입을 선언하는 방식const printMessage = (message: string | number) => {
return message;
}
const message1 = printMessage(1234);
const message2 = printMessage('hello world!');
// string과 number type의 공통된 메소드만 사용 가능하기 때문에 error출력 (string에 존재하여도)
console.log(message2.length);
function add<T extends string | number | boolean>(a: T, b: T) {
if (typeof a === 'boolean') return a || b;
return <any>a + <any>b;
}
console.log(add<number>(13, 15));
console.log(add<string>('hell', 'o'));
console.log(add<boolean>(false, true)); // error
const getProperty = <T extends object, U extends T>(obj: T, key: U) => {
return obj[key];
}
getProperty({a: 1, b: 2, c: 3}, "a"};
// error: Generic T는 키 값이 a, b, c만 존재하기 때문
getProperty({a: 1, b: 2, c: 3}, "z"};
interface Car {
drive(): void;
park(): void;
}
class Bus implements Car {
drive(): void {}
park(): void {}
}
class Taxi implements Car {
drive(): void {}
park(): void {}
}
class CarFactory {
static getInstance<T extends Car>(type: {new (/*no parameter*/): T}): T {
return new type();
}
}
const bus = CarFactory.getInstance(Bus);
const taxi = CarFactory.getInstance(Taxi);
new (): T
는 typescript의 constructor signature다.class Test {
constructor(a: number){
...
}
}
// would be {new(a: number): Test}