인터페이스 (interface)
interface ProductModel { // 인터페이스 선언
id: number;
}
// productModel 인터페이스를 타입으로 갖는 product 객체를 받아 콘솔로 찍음
const printProduct = (product: ProductModel) => {
console.log(product);
};
let myProduct = { id: 10, productName: "my first product" };
printProduct(myProduct); // {id: 10, productName: "my first product"}
인터페이스는 정의된 프로퍼티가 있는지와, 이 프로퍼티의 타입이 맞는지만 검사한다.
정의되지 않은 프로퍼티는 검사하지 않고, 프로퍼티의 순서도 상관없다.
옵셔널 프로퍼티 (Optional Properties)
interface ProductModel {
id: number;
productName?: string;
}
옵셔널 프로퍼티는 프로퍼티명 끝에 ?를 붙인다.
이 productName 프로퍼티는 있을수도있고 없을수도 있지만, 있다면 string 타입을 가진다.
읽기 전용 프로퍼티 (Readonly properties)
interface ReadModel {
readonly a: number;
readonly b: number;
}
let test:ReadModel = {
a:10;
b:15;
}
test.a = 11; // Cannot assign to 'a' because it is a read-only property.
말 그대로 읽기전용이므로, 값 할당이후 수정할 수 없다.
타입스크립트는 Array<T>와 ReadonlyArray<T> 타입을 제공하는데, 이 둘은 변경 메서드가 제거되었기 때문에 재할당이 불가능하다.
let readtest: ReadonlyArray<number> = [1, 2, 3];
console.log("첫번째", readtest); // [2,2,3] 이거 왜 2찍혀??
readtest[0] = 2; // Index signature in type 'readonly number[]' only permits reading.
readtest.push(4); // Property 'push' does not exist on type 'readonly number[]'.
readtest.length = 3; // Cannot assign to 'length' because it is a read-only property.
readtest = [1, 2, 3, 4]; // 근데 이건 왜 돼??
console.log("두번째", readtest); // [1,2,3,4]
let으로 선언한 변수 readtest가 읽기전용이지만, 변수자체를 다른값으로 할당하는것은 된다. (다른 주소값을 할당)
참고로 위 예제에서 readtest[0]을 2로 할당한 줄에서 에러가 발생 했지만 콘솔은 찍힌다ㅋㅋ
readonly 와 const 어떤것을 사용해야할까?
변수에는 const를 쓰고, 프로퍼티에는 readonly를 사용한다.
초과 프로퍼티 검사 (Excess Property Checks)
Typescript는 객체 리터럴을 다른 변수에 할당할때나 인수로 전달할 때 초과 프로퍼티 검사를 한다.
예를들어, 없는 프로퍼티를 넘길때 에러가 발생한다.
interface ProductModel {
id?: number;
productName?: string;
}
function createProduct(product: ProductModel){
console.log(product);
}
let productOne = createProduct({ ids: 123, productName: "product One" });
// Object literal may only specify known properties,
// and 'ids' does not exist in type 'ProductModel'.
이럴때는 해결하는 방법은 3가지가 있다.
1. as 타입단언
let productOne = createProduct({ ids: 123, productName: "product One" } as ProductModel);
타입을 단언하는것은 별로 좋아보이진 않는다.
2. 문자열 인덱스 서명(string index signature)
interface ProductModel {
id?: number;
productName?: string;
[holly: string]:any; //프로퍼티명은 string이고, 그 타입은 any인 것
}
이렇게 문자열 인덱스 서명방식을 추가하면 어떤 것이 들어와도 에러가 발생하지 않는다.
3. 객체를 다른 변수에 할당
interface ProductModel {
id?: number;
productName?: string;
}
function createProduct(
product: ProductModel
){
console.log(product);
}
let obj = { ids: 123, test:12, productName: "product One" };
let productOne = createProduct(obj); //이게 왜 돼?
obj는 초과 프로퍼티 검사를 받지 않으므로 에러가 발생하지 않는다. (인자에 그대로 넘기면 발생)
하지만 이 방법은 obj 변수에 ProductModel에서 명시한 프로퍼티가 존재하지 않다면 에러가 난다. 좋은 방법은 아니다.
함수 타입
인터페이스는 함수 타입도 선언할수있다.
interface UserFunction { // name, age를 인자로 받고 boolean을 리턴하는 함수
(name: string, level: number): boolean;
}
let firstUserCreator: UserFunction; // 변수에 타입선언
firstUserCreator = (name, level) => { // 변수에 함수할당. 이때는 타입선언을 안해줘도 타입추론이 된다.
console.log(name);
return level > 19;
};
console.log(firstUserCreator("rumi", 999) ? "참" : "거짓"); // 참
인덱서블 타입
name['rumi'] 나 level[99] 처럼 타입을 인덱스로 지정할수있다.
import "./global.css";
import * as React from "react";
interface levelArray {
[level: number]: number;
}
let userLevel: levelArray = [99, 12, 43];
let level: number = userLevel[0];
console.log(level); //99
이 인덱스 서명을 지원하는 타입은 string와 number 두가지다. 숫자 인덱서에서 반환된 타입은 문자열 인덱서에서 반환된 타입의 하위 타입(subtype)이어야 하는데, 그 이유는 실제로 javascript가 객체를 인덱싱 하기 전에 string으로 변환하기 때문이다.
interface Origin {
[index: string]: number;
length: number; // length는 숫자입니다
name: string; // Property 'name' of type 'string' is not assignable to 'string' index type 'number'.
}
// index:string으로 선언한 타입이 number이므로 name도 number 타입을 가질수있어야한다.
인터페이스 확장 (interface extends)
인터페이스는 확장할 수 있다.
interface UserModel{
id:number;
name:string;
level:number;
}
interface VipUserModel extends UserModel{
priceing:string;
hiddenLevel:number;
}
let user:UserModel;
let vipUser:VipUserModel;
하이브리드 타입 (Hybrid Types)
함수 인터페이스, as 타입단언 등을 여러가지 타입패턴을 섞어만든 타입.
'[STUDY] 스터디 > TypeScript' 카테고리의 다른 글
[Typescript] 네임스페이스 ts / 타입스크립트 모듈 import export (0) | 2023.07.14 |
---|---|
TypeScript utility type / 타입스크립트 유틸리티 타입 (0) | 2023.06.23 |
[Typescript] 타입스크립트 리터럴 / typescript literal types / 문자열 리터럴, 숫자형 리터럴 타입 (0) | 2023.06.16 |
[Typescript] 타입스크립트 함수 타입 / function type (0) | 2023.06.10 |
[Typescript] 타입스크립트 기본타입 / typescript enum / typescript any / typescript void / typescript unknown (0) | 2023.06.07 |