티스토리 뷰
공부를 시작하며
타입스크립트에서 객체의 타입을 지정하는 방법에 대해서 공부를 시작합니다.
타입스크립트 문서를 통해서 공부를 했습니다.
레퍼런스 : https://www.typescriptlang.org/docs/handbook/2/objects.html
일반적으로 객체에 타입을 지정
익명 타입으로 지정하는 방법
function printUser(user: { name: string; age: number }) {
console.log(`My name is ${user.name}. I'm ${user.age} years old.`);
}
인터페이스로 지정하는 방법
interface User {
name: string;
age: number;
}
function printUser(user: User) {
console.log(`My name is ${user.name}. I'm ${user.age} years old.`);
}
타입 별칭으로 지정하는 방법
type User = {
name: string;
age: number;
};
function printUser(user: User) {
console.log(`My name is ${user.name}. I'm ${user.age} years old.`);
}
속성 수정자 Property Modifiers
선택적 속성 (Optional Property)
선택적으로 부여해야하는 속성(property)과 같은 경우에는 ?를 사용합니다.
interface User {
name: string;
age?: number;
address?: string;
}
function printUser(user: User) {
// ...
}
printUser({ name: "Jone" });
printUser({ name: "Jone", age: 20 });
printUser({ name: "Jone", age: 20, address: "South Korea" });
잠재적 undefined
선택적 속성의 값은 잠재적으로 undefined 라고 인식합니다.
interface User {
name: string;
age?: number;
address?: string;
}
function printUser(user: User) {
const age = user.age;
}
따라서 다음과 같이 undefined 일 때의 처리가 필요합니다.
이때 여러 방법으로 처리가 가능하겠지만 간단하게 삼항 연산자로 해결이 가능합니다.
function printUser(user: User) {
const age = user.age === undefined ? 0 : user.age;
}
객체 구조 분해와 기본값 할당
더 쉽게는 객체 구조 분해로 기본값을 할당하여 해결도 가능합니다.
function printUser({ name, age = 0, address = "" }: User) {
const getAge = age;
// (parameter) age: number
}
readonly 속성
readonly 속성을 사용해서 오직 값을 읽는데에만 사용할 수 있도록 설정할 수 있습니다.
해당 속성이 추가된 속성을 임의로 변경하려 하면 타입스크립트에서는 오류를 표시해줍니다.
interface ReadonlyType {
readonly property: string;
}
function readOnly(option: ReadonlyType) {
console.log(option.property);
option.property = "test";
// Cannot assign to 'property' because it is a read-only property.
}
readonly가 변경이 될 수 도 있는 상황
readonly 속성을 사용하면 항상 변경이 되지 않는다는 뜻은 아닙니다. 다음과 같이 객체의 내부 속성의 값을 변경하려고 하면 오류가 표시되지 않습니다.
interface User {
name: string;
readonly inform: { age: number };
}
function printUser(user: User) {
user.inform.age++;
}
readonly를 타입 별칭을 통해서 지정하고 수정하기
interface User {
name: string;
age: number;
}
interface ReadonlyUser {
readonly name: string;
readonly age: number;
}
let writeableUser: User = {
name: "Jone",
age: 24,
};
let readonlyUser: ReadonlyUser = writeableUser;
console.log(readonlyUser.age);
// 24
writeableUser.age = 30;
console.log(readonlyUser.age);
// 30
readonlyUser.age = 30;
// Cannot assign to 'age' because it is a read-only property.
인덱스 서명 ( Index Signatures )
타입의 프로퍼티의 이름을 다 모르지만 유형을 알고 있을때 인덱스 서명(index signatures)를 사용합니다.
다음은 배열의 인덱스 서명 예시입니다. 배열의 index는 number 타입이고 각 배열의 아이템들을 number 타입으로 지정할 때 예시입니다.
interface NumberArray {
[index: number]: number;
}
const numberArray: NumberArray = [];
numberArray[0] = 1;
numberArray[1] = "2";
// Type 'string' is not assignable to type 'number'.
readonly 를 통해서 인덱스 할당을 방지할 수 있습니다.
interface NumberArray {
readonly [index: number]: number;
}
const numberArray: NumberArray = [];
numberArray[0] = 10;
// Index signature in type 'NumberArray' only permits reading.
타입 확장 ( Extending Types )
다음과 같이 shape 속성을 가지는 타입이 있습니다.
interface Shape {
x: number;
y: number;
fill: string;
}
그리고 사각형의 속성을 가지는 타입이 있습니다. 타입의 프로퍼티가 shape에서 가지고 있는 속성을 반복적으로 가지고 있습니다.
interface Rect {
type: "rect";
x: number;
y: number;
fill: string;
width: number;
height: number;
}
이럴때 shape 타입의 속성을 가지는 타입을 확장할 수 있습니다.
extends
다음과 같이 extends (확장)이라는 구문으로 속성을 확장할 수 있습니다. 다음의 Rect 인터페이스는 Shape 타입의 속성들을 포함하게 됩니다.
interface Shape {
x: number;
y: number;
fill: string;
}
interface Rect extends Shape {
type: "rect";
width: number;
height: number;
}
2개 이상 extends
2개 이상의 인터페이스를 확장하기 위해서는 , 를 통해서 확장할 수 있습니다.
interface Shape {
x: number;
y: number;
}
interface Styles {
fill: string;
stroke?: string;
}
interface Rect extends Shape, Styles {}
Intersection Types 타입 교차
interface를 통해서 타입을 확장하는 것 외에 타입스크립트에서는 & 연산자를 통해서 교차로 확장할 수 있는 방법을 제공해줍니다.
interface Shape {
x: number;
y: number;
}
interface Styles {
fill: string;
stroke?: string;
}
type Rect = Shape & Styles & {};
제네릭을 통한 타입 확장
Before
다음과 같이 비슷하지만 다른 타입이 3가지 있습니다.
비슷한 타입이 여러개 생성이 되면 타입 별로 타입을 생성해 줘야할 것입니다.
다음 After 에서의 예시로 좀 더 나은 방법으로 타입을 유연하게 대처하는 방법을 살펴봅니다.
interface StringContents {
content: string;
}
interface NumberContents {
content: number;
}
interface BooleanContents {
content: boolean;
}
After
다음과 같이 제네릭 타입을 사용해서 사용될 타입을 추론하도록 할 수 있습니다.
interface Contents<T> {
content: T;
}
const obj: Contents<string> = {
content: "this is string contents",
};
Array 타입에서의 제네릭
interface ArrayType<T> {
array: T[];
}
const information: ArrayType<number> = {
array: [1, 2, 3, 4, 5],
};
ReadonlyArray 타입
readonly 를 제네릭과 쓸 수 있는 특별한 타입인 ReadonlyArray 와 같은 타입이 있습니다.
다음과 같이 ReadonlyArray 에서 제네릭을 사용하는 것과 같이 사용합니다.
function onlyReadArray(array: ReadonlyArray<string>) {
// 읽기
const copy = array.slice();
const lastValue = array[array.length - 1];
// 변경
array.push("123");
// Property 'push' does not exist on type 'readonly string[]'.
}
튜플 타입 ( Tuple Types )
array 의 배열 갯수를 제한하는 방법중 튜플 타입이 있습니다.
다음과 같이 간단하게 선언 가능합니다.
type TupleNum = [number, number];
튜플 타입을 지정하면 배열 구조 분해를 통해서도 각 타입을 확인하고 사용할 수 있습니다.
type Tuple = [string, number];
function tupleArr(getTupleArr: Tuple) {
const [string, number] = getTupleArr;
// string : string
// number : number
}
readonly tuple type
상수 단언으로 readonly 튜플 타입을 생성해 줄 수도 있습니다.
const tuple = [1, 2] as const;
// const tuple: readonly [1, 2]
optional tuple type
옵셔널하게 튜플 타입을 받을 수 있습니다. 간단하게 다음과 같이 받는 배열의 뒤에 ? 연산자를 붙이면 됩니다.
그리고 받는 튜플 타입의 length의 타입을 보게되면 다음과 같이 2 또는 3개의 갯수일 수 도 있다고 판단합니다.
type Points = [number, number, number?];
function addPoints(points: Points) {
//...
const [x, y, z] = points;
// const z: number | undefined
console.log("points length: ", points.length);
// (property) length: 2 | 3
}
Rest Tuple type
다음과 같이 ... 스프레드 연산자를 사용해서 튜플 타입을 지정해줄 수 있습니다.
type StringNumberRestBoolean = [string, number, ...boolean[]];
type StringRestBooleanNumber = [string, ...boolean[], number];
let test1: StringNumberRestBoolean = ["1", 2, true, false, true];
let test2: StringRestBooleanNumber = ["1", true, false, true, 2];
'Typescript' 카테고리의 다른 글
[ Typescript ] function 타입스크립트에서의 함수 (0) | 2022.09.07 |
---|---|
[ Typescript ] Narrowing 좁히기 (0) | 2022.09.05 |
[Typescript] 타입 스크립트의 기본 (0) | 2022.09.03 |
[Typescript] 타입스크립트 핸드북 시작하기 (0) | 2022.09.03 |