(지난 날.. 나의 코드는 any 범벅...)
인프런 한 입 크기로 잘라먹는 타입스크립트 강의를 기반으로 정리했습니다. 보시다가 잘못된 정보를 발견하신다면 댓글을 남겨주시면 감사하겠습니다 :)
새롭게 배우고 싶거나 배울 필요성을 느끼는 프로그래밍 언어를 한 가지 골라주세요. 라는 프로그래머스 사이트 질문에서 프론트엔드 직무는 1위로 타입스크립트를 뽑았습니다. 이 설문조사만 봐도 타입스크립트는 압도적인 인기를 얻고 있습니다.
이렇게 인기가 많은 타입스크립트를 한 마디로 정의하자면...!
타입스크립트란?
타입스크립트는 자바스크립트의 확장판입니다.
자바스크립트는 자유로운 문법을 가지고 있어 프로그래머가 쉽고 빠르게 코드를 작성할 수 있는 장점이 있습니다. 그러나 이러한 자유로움은 버그의 발생 가능성을 높여 매우 취약한 측면을 가지고 있습니다. 또한, 자바스크립트는 웹 브라우저에서만 동작한다는 한계점을 가지고 있습니다.
이 때, Node.js가 등장하게 되었습니다. Node.js는 JavaScript 런타임 환경으로, JavaScript로 서버를 개발하거나 어플리케이션을 만들 수 있게 해줍니다. 이로 인해 자바스크립트는 더욱 큰 인기를 얻게 되었습니다.
하지만, 자바스크립트는 엄격하지 못하고 자유로운 특성을 가지고 있어 복잡한 대규모 어플리케이션에서 프로그램의 안전성
을 떨어뜨릴 수 있습니다. 이를 보완하기 위해 타입스크립트가 등장하였습니다. 타입스크립트는 대규모 프로젝트에서 안전장치로써 타입을 추가하여 개발을 안정적으로 할 수 있는 도구입니다.
방금 말한 프로그램의 안전성의 예시를 들어보도록 하겠습니다.
let a = "hello" //문자열
a= 19980505 //숫자
a.toUpperCase();
위 코드를 실행하면 오류가 발생합니다. toUpperCase()는 문자열에만 적용할 수 있는 메서드이지만, 위의 코드에서는 숫자에 적용하려고 시도하고 있습니다. 따라서 오류가 발생하는 것은 당연합니다.
이러한 상황에서 우리는 신중하게 고려해야 할 문제를 직면하게 됩니다. 코드가 실행되고 나서 오류가 발생한다는 점입니다. 실행 중에 오류가 발생하면 심각한 문제가 될 수 있기 때문에 주의해야 합니다.
타입스크립트와 같은 언어는 이를 미리 방지하기 위해 실행 전에 타입 체크를 수행하여 오류를 방지합니다. 프로그램이 실행되기 전에 타입 오류를 발견
할 수 있어 매우 유용합니다. 이를 통해 프로그램의 안정성을 높일 수 있습니다.
타입스크립트 코드는 AST로 변환하고 타입을 검사한 후 타입에 오류가 있다면 컴파일이 중단됩니다. 타입검사를 통과하면 자바스크립트코드로 변환되고 AST변환과 바이트코드 변환을 거쳐 실행이 됩니다. (대부분 프로그래밍 언어는 AST로 변환하고 AST를 다시 바이트 코드로 변환후 실행됩니다.)
타입스크립트가 내장하고 있는 다양한 기본타입이 있습니다.
원시타입은 하나의 값만 저장하는 타입입니다.
//1.number
let num1: number = 123;
let num1: number = -123;
let num1: number = 0.123;
let num1: number = -0.123;
let num1: number = Infinity;
let num1: number = -Infinity;
let num1: number = NaN;
//number 타입에러
num1.toUpperCase() //숫자타입에 문자와 관련된 메서드는 사용할 수 없다.
//2.string타입
let str1: string = "hello";
let str1: string = `hello`;
let str1: string = 'hello';
let str1: string = `hello ${num1}`;
//string 타입에러
str1.toFixed() //문자타입에 숫자와 관련된 메서드는 사용할 수 없다.
//3.boolean
let bool1: boolean = true;
let bol2: boolean = false;
//4.null
let null1: null = null;
//5.undefined
let unde1: undefined = undefined;
리터럴 타입은 값을 나타내는 타입입니다.
let numA: 10 = 10;
numA = 12; //10이 아닌 다른 숫자를 넣으면 타입에러!!
배열타입은 배열을 저장하는 변수의 이름 뒤에 타입 주석의 시작을 의미하는 콜론(:)을 작성한 다음 배열요소타입[] 형식으로 배열 타입을 정의합니다.
let numArr: number[] = [1, 2, 3];
let strArr: Array<boolean> = [true, false, true];
//배열에 들어가는 요소들의 타입이 다양할 경우
let multiArr: (number | string)[] = [1, "hello"];
//다차원 배열의 타입을 정의하는 방법
let doubleAr: number[][] = [
[1, 2, 3],
[4, 5],
];
튜플타입은 자바스크립트에는 없는 타입스크립트의 특수한 타입으로 길이와 타입이 고정된 배열을 의미합니다.
let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, "2", 3]; //타입에러!!!
튜플 언제 사용하나요?
회원정보를 2차원 배열로 저장하기로 했습니다. 각 배열의 0번 인덱스에는 회원이름을 저장해두고 1번 인덱스에는 회원의 나이를 저장해 두었을 때, 누군가 순서를 잘 못 배치하면 문제가 일어날수 있습니다. 이러한 문제를 방지할때 튜플을 사용합니다.
const users = [
["메리", 20],
["이아무개", 25],
["김아무개", 30],
["박아무개", 40],
[22, "조아무개"], // <- 새로 추가함
];
//통일성이 무너짐...이럴때 튜플타입 추가!!
const users:[string, number][] = [
["메리", 20],
["이아무개", 25],
["김아무개", 30],
["박아무개", 40],
[22, "조아무개"], // <- 타입 에러!!!
];
객체 리터럴타입은 객체에 모든 프로퍼티들 타입까지 정의하여 사용해야 합니다.
let user: object = {
id: 1,
name: "메리",
}
user.id; //타입에러!!! 자바나 c언어에서는 객체 타입을 object라고 명시를 하면 끝이지만..타입스크립트는 에러발생!!
let user: {
id: number;
name: string;
} = {
id: 1,
name: "메리",
}
user.id; // 모든 프로퍼티들 타입까지 정의해줘야 합니다.
특수한 프로퍼티 정의하기
선택적 프로퍼티 : 있어도 되고 없어도 되는 프로퍼티의 이름 뒤에 ?룰 붙여줍니다.
let user: {
id?: number; // 선택적 프로퍼티가 된 id
name: string;
} = {
id: 1,
name: "메리",
};
user = {
name: "홍길동",
};
읽기전용 프로퍼티 : 특정 프로퍼티에 readonly 키워드를 붙여 읽기전용으로 만들 수 있다.
let user: {
id?: number;
readonly name: string; // name은 이제 Readonly 프로퍼티가 되었음
} = {
id: 1,
name: "메리",
};
user.name = "dskfd"; // 오류 발생
터입별칭? 타입을 변수처럼 정의하여 사용할 수 있습니다.
//타입중복 코드 발생 예시 코드
let user: {
id: number,
name: string,
nickname: string,
birth: string,
bio: string,
location: string,
} = {
id: 1,
name: "메리",
nickname: "winterlood",
birth: "1997.01.07",
bio: "안녕하세요",
location: "부천시",
};
let user2: {
id: number,
name: string,
nickname: string,
birth: string,
bio: string,
location: string,
} = {
id: 1,
name: "메리",
nickname: "winterlood",
birth: "1997.01.07",
bio: "안녕하세요",
location: "부천시",
};
//타입 중복코드를 제거하기 위해 타입별칭을 사용한다.
type User = {
id: number,
name: string,
nickname: string,
birth: string,
bio: string,
location: string,
}
let user: User = {
id: 1,
name: "메리",
nickname: "merry",
birth: "1997.01.07",
bio: "안녕하세요",
location: "부천시",
};
let user2: User = {
id: 1,
name: "메리",
nickname: "merry",
birth: "1997.01.07",
bio: "안녕하세요",
location: "부천시",
};
//타입별칭 같은 스코프내 사용시 에러 발생
type User = {
id: number,
name: string,
nickname: string,
birth: string,
bio: string,
location: string,
}
type User = {
id: number,
name: string,
nickname: string,
birth: string,
bio: string,
location: string,
} //error
function func() {
type User = {};
} //다른 스코프에 있기 때문에 괜춘!
인덱스 시그니처? key와 value 규칙에 맞게 타입 정하기
type CountryCodes = {
[key: string]: string;
}
let countryCodes: CountryCodes = {
Korea: "ko",
UnitesState: "us",
UnitedKingdom: "uk",
}
Enum타입은 여러가지 값들에 각각 이름을 부여해 열거하여 사용하는 타입입니다.
enum Role {
ADMIN = 0, //만약 별도의 값이 설정되지 않은 경우 기본적으로 0부터 시작합니다.
USER = 1,
GUEST = 2,
}
enum Language {
korean = "ko",
english = "en",
}
const user1 = {
name: "메리",
role: Role.USER ,
language: Language.korean,
}
const user2 = {
name: "홍길동",
role: Role.ADMIN,
language: Language.english, //컴파일 되고 나서 enum이 자바스크립트 객체로 변환된다.
}
const user2 = {
name: "홍길동",
role: Role.GUEST,
}
any 타입은 특정 변수의 타입을 확실히 모를때 사용합니다. any를 쓴다고 하면 타입스크립트를 사용하지 않겠다는 이야기입니다... 사용을 피합시다. 또한 any는 런타임때 에러를 일으킵니다.
let anyVar = 10;
anyVar = "hello"; //타입 error 발생. 타입스크립트는 초기화하는 값으로 변수에 타입을 자동 추혼합니다. 지금 숫자타입 10으로 추론되고 있기 때문에 문자열이 들어갈 수 없습니다.
//하지만 any를 사용하면 가능합니다. 무서운 아이입니다.
let anyVar: any = 10;
anyVar = "hello";
anyVar = true;
anyVar = {};
anyVar = () => {}; //함수를 넣음.
anyVar.toUpperCase(); //함수에서 toUpperCase()를 사용할수가 없다. 근데 이 에러가 런타임에서 발생함. 결국 any를 쓴다는것은 타입스크립트 쓰지 않겠다는 이야기...>!!
anyVar.toFixed();
anyVar.a;
unknown타입은 any와 비슷하지만 any보다 더 안전한 타입입니다. any 타입을 써야한다면 unknown타입을 사용하세요!
let num: number = 10;
let unknownVar: unknown;
unknownVar = "";
unknownVar = 1;
unknownVar = () => {};
//any처럼 모든 타입을 넣을 수 있지만 ...!
num = unknownVar; //num이라는 숫자타입 변수에 unknown타입을 할당 할 수 없습니다. (any는 가능)
unknownVar.toUpperCase(); //절대 허용이 안됩니다.(any는 가능)
void타입은 아무런 값도 반환하지 않는 함수의 반환값 타입을 정의할 때 사용합니다.
function func2(): void {
console.log("hello");
}
never타입은 함수가 어떠한 값도 반환할 수 없는 상황일 때 사용합니다.
//무한루프를 돌기 때문에 아무런 값도 반환할 수 없습니다.
function func3(): never {
while (true) {}
}