interface는 상호 간에 정의한 약속 혹은 규칙을 의미함.
// 기본 type 지정
let car = { brand: 'kia', createdAt: 2022 };
function abc(obj: { createdAt: number }) {
console.log(obj.createdAt);
}
abc(car); -> 2022
// interface 적용
interface carInfo {
createdAt: number
}
function abc(obj: carInfo) {
console.log(obj.createdAt);
}
let car = { brand: 'kia', createdAt: 2022 }
abc(car); -> 2022
->
abc()의 인자가 좀 더 명시적으로 바뀌었다.
abc() 의 인자는 carInfo 라는 타입을 가져야한다.
// interface에 하나의 타입을 더 추가한다.
interface carInfo {
brand: string;
createdAt: number;
price: number;
}
function abc(obj: carInfo) {
console.log('abc 함수 실행 : ', obj.createdAt);
}
let car = { brand: 'kia', createdAt: 2022 };
abc(car); // 에러! 아래참고
위 코드에선 다음과 같은 typescript 에러가 나온다.
->
'{ brand: string; createdAt: number; }' 형식의 인수는 'carInfo' 형식의 매개 변수에 할당될 수 없습니다. 'price' 속성이 '{ brand: string; createdAt: number; }' 형식에 없지만 'carInfo' 형식에서 필수입니다.ts(2345)
즉, carInfo형식에서 price: number가 필수적이지만 car라는 인수(price속성이 없는)가 할당시키려해서 발생하는 에러가 나오는것이다.
위와같은 에러에선 ?
를 속성 끝에 붙여서 해결한다.
interface carInfo {
brand: string;
createdAt: number;
price?: number; // ?를 붙여서 에러를 해결하였다.
}
function abc(obj: carInfo) {
console.log('abc 함수 실행 : ', obj.createdAt);
}
let car = { brand: 'kia', createdAt: 2022 };
abc(car);
옵션 속성의 장점
은 인터페이스를 사용할 때 속성을 선택적으로 적용할 수 있다는 것 뿐만 아니라 인터페이스에 정의되어 있지 않은 속성에 대해 인지시켜줄 수 있다.
읽기 전용 속성은 인터페이스로 객체를 처음 생성할 때만 값을 할당하고 이후에는 변경할 수 없는 속성을 의미한다.
아래처럼readonly
속성을 앞에 붙인다.
// 인터페이스로 객체를 생성 후 객체 속성값 변경!
interface carInfo {
brand: string;
}
let car: carInfo = { brand: 'kia', createdAt: 2022 };
car.brand = 'hyundai';
console.log(car); -> { brand: 'hyundai', createdAt: 2022 }
// readonly 속성 추가 했을때 변경하려한다면?
interface carInfo {
readonly brand: string;
}
let car: carInfo = { brand: 'kia', createdAt: 2022 };
car.brand = 'hyundai'; // 에러! 아래 참고!
console.log(car);
위의 에러는 다음과 같이 나온다.
->
읽기 전용 속성이므로 'brand'에 할당할 수 없습니다.ts(2540)
ReadonlyArray<T>
타입을 사용하면 읽기 전용 배열을 생성가능!
ReadonlyArray
로 선언하면 배열을 선언하는 시점에만 값을 정의 할 수 있다.
let arr: ReadonlyArray<number> = [0,1,2,3,4];
arr.push(5); // 에러!
arr[1] = 30; // 에러!
interface carInfo {
brand?: string;
}
function abc(obj: carInfo) {
}
abc({createdAt: 2022}); // 에러! carInfo형식에 createdAt 가 없다.
위와 같은 에러가 나온다.
만약 이런 타입 추론을 무시하고 싶다면 아래와 같이 선언한다.
interface carInfo {
brand?: string;
}
function abc(obj: carInfo) {
}
abc({createdAt: 2022} as carInfo);
만약 인터페이스에 정의하지 않은 속성들을 추가로 사용하고 싶을때는 아래와 같은 방법을 사용한다.
interface carInfo {
brand?: string;
[propName: string]: any; // propName이라는 속성이 있는게 아니라 아무렇게나 이름을 지어도 된다. ex. [a: string]: any
}
function abc(obj: carInfo) {
}
abc({createdAt: 2022});
interface는 함수의 타입을 정의할 때에도 사용 가능!
interface login {
(id: string, pw: string): boolean;
}
let isLogin: login;
isLogin = function() {
return true;
}
isLogin('testId', '12345') -> true
interface carBrand {
brand: string;
}
interface carName extends carBrand { // extends 를 사용하여 상속 가능!
name: string;
}
let car = {} as carName;
car.name = 'sportage';
car.brand = 'kia';
console.log(car); -> {name: 'sportage', brand: 'kia'}
추가적으로 속성을 넣고 싶다면?
interface carBrand {
brand: string;
}
interface carName extends carBrand {
name: string;
[propName: string]: string;
}
let car = {} as carName;
car.name = 'sportage';
car.brand = 'kia';
car.price = '4100';
console.log(car); -> {name: 'sportage', brand: 'kia', price: '4100'}