🤔타입 선언?
자바스크립트와 타입스크립트의 가장 큰 차이점은 변수에 타입을 지정해주는 것에 있다. Java와 C언어와 달리 따로 타입을 지정해주지 않는 자바스크립트는 런타임 후 버그를 발견 할 수 있는 동적 언어 타입이다. 동적언어의 가장 큰 단점이 에러를 늦게 발견한다는 것인데, 이 때문에 자바스크립트 대신 타입스크립트를 쓰는 이유다. 실제로 자바스크립트의 버그중 15%를 타입스크립트로 없앨 수 있다는 결과가 있다.
+ 컴파일 단계에서 바로 에러를 수정할 수 있기 때문에 에러 지점을 바로 파악하기 쉽다.
1️⃣원시 타입 선언 방법
//number
let num1:number=123;
// string
let str1:string = "hello";
//boolean
let bool1: boolean = true;
//null
let null1: null=null;
//undefined
let unde1: undefined = undefined;
// 리터럴 타입(잘 쓰일 일은 없음)
// 리터럴 -> 값
// 한번 지정되면 다른 값은 넣을 수 없음
let numA:10 = 10;
let strA:"hello" = "hello";
여기서 기억할 점은 리터럴 타입이다.
리터럴 타입은 한번 지정하면 바뀌지 않는다. 따라서 let으로 변수를 선언했음에도 const로 선언을 한거나 다름이 없다.
2️⃣ 배열 & 튜플 타입 선언
1. 배열
// 배열
let numArr:number[] = [1,2,3]
let booleanArr:boolean[] = [false,true,false]
// 배열에 들어가는 요소들의 타입이 다양할 경우
let multiArr:(number | string)[] = [1,"hello",3]
// 다차원 배열의 타입을 정의하는 방법
let doubleArr:number[][] = [
[1,2,3],
[4,5]
]
배열 타입을 선언할 경우 배열안의 요소들의 타입을 선언해준 후 배열표시를 선언해 "~~타입으로 된 배열"이라고 선언해준다. 반드시 요소들의 타입을 지켜야 하며, 만약 여러 타입의 요소가 배열안에 들어가 있다면 "|" 연산자를 통해 선언해 주면 된다.
+ 다차원 배열은 필요한 만큼 "[ ]" 를 추가해주면 된다.
2. 튜플
자바스크립트에는 없는 튜플이다. 튜플은 기본적으로 배열의 형태를 가지며, 차이점은 길이와 타입이 고정되어 있다고 생각하면 된다. 참고로 JS파일로 컴파일하면 JS 파일에서는 그냥 배열로 보인다.
// 튜플
// 길이와 타입이 고정된 배열
let tup1:[number,number] = [1,2];
//tup1 = [1,2,3]; //안됌
//tup1 = ["1","2"]; //안됌
let tup2:[number,string,boolean] = [1,"2",true];
const users:[string,number][] = [
["이아무개",2],
["박아무개",3],
["김아무개",4],
//[5,"아몰라"] //안됌
]
무조건 순서와 타입이 일치해야만 튜플에 추가할 수 있다.
3️⃣ 객체 타입 선언
// object
let user:{
id?:number, // ?표의 의미: 있을 수도 있고 없을 수도있다.(선택적 프로퍼티)
name:string
} = {
id:1,
name:"조진형"
}
// 객체 리터럴 타입
let dog:{
name:string,
color:string
} = {
name:"돌돌이",
color:"brown",
}
let config:{
readonly apikey:string // readonly = 값이 절때 바뀌면 안되는 프로퍼티에 추가
} = {
apikey:"MY API KEY",
}
객체 타입은 key에 대한 value들의 타입을 선언해줘야 한다.
특이한 점은 2가지 있다. 선택적 프로퍼티와 readonly.
1. 선택적 프로퍼티
let user:{
id?:number, // ?표의 의미: 있을 수도 있고 없을 수도있다.(선택적 프로퍼티)
name:string
} = {
id:1, //없어도 가능
name:"조진형"
}
여기서 id 값이 선택적 프로퍼티다. 따라서 id값은 객체를 선언할 때 있어도 되고 없어도 된다.
2. readonly
let config:{
readonly apikey:string // readonly = 값이 절때 바뀌면 안되는 프로퍼티에 추가
} = {
apikey:"MY API KEY",
}
API키와 같이 절때 변하면 안되는 값들이 있다. 이런 값들은 readonly속성을 추가해 변하지 않게 해준다.
다른 말로 하면 const나 리터럴 타입과 비슷하게 바뀐다고 생각하면 될 거 같다.
4️⃣ 타입 별칭 & 인덱스 시그니쳐
1. 타입 별칭
이것도 자바스크립트에는 없는 개념이다. 변수를 선언하듯 타입들을 선언해줄 수 있다.
// 타입 별칭
type User = {
id:number
name:string
nickname:string,
birth:string,
bio:string,
location:string,
}
// type User={} // 에러
function func(){
// 타입은 해당 스코프 내에서만 사용할 수 있다.
// 이 함수 내에서는 아래의 User가 사용된다.
type User={}
}
let user:User = {
id: 1,
name:"진",
nickname:"jin",
birth:"1999.06.12",
bio:"안녕하세요",
location:"수원시"
}
여기서 주의할 점은 타입별칭도 변수와 동일한 스코프를 가진다. 따라서 같은 스코프 안에 중복된 타입별칭 선언은 불가하다.
함수 밖과 안에 같은 이름의 타입별칭을 선언 했다고 가정하면, 함수 안에서 타입별칭을 호출하면 함수 안의 타입별칭이 호출된다.
2. 인덱스 시그니쳐
타입 별칭에 반복적으로 동인한 키의 타입과 값들의 타입이 나올 경우 변수의 수 만큼 계속 타입을 똑같은 타입을 지정해줘야 하는 번거로움 있다. 그래서 위의 조건을 만족한다면 한줄로 퉁! 칠 수 있다.
type CountryCodes = {
[key : string] : string;
}
let countryCodes: CountryCodes = {
korea:"ko",
UnitedState:"us",
UnitedKingdom:"uk"
}
type CountryNumberCodes = {
[key:string] : number;
// 반드시 넣어줘야 하는 객체가 있으면 따로 추가해 줘도 된다. 단 반드시 인덱스 시그니쳐의 타입과 같아야 한다.
Korea : number;
}
let countryNumberCodes:CountryNumberCodes = {
Korea:410,
}
5️⃣ enum 타입
여러가지 값들에 이름을 부여해 열거해두고 사용하는 타입이다.
//enum 타입
enum Role{
ADMIN,
USER,
GUSET
}
enum Language {
korean = "ko",
english = "en"
}
const user1 = {
name:"조진형",
role:Role.ADMIN,
Language:Language.korean
}
const user2 = {
name:"홍길동",
role:Role.GUSET
}
const user3 = {
name:"아무개",
role:Role.USER
}
현재 Role.ADMIN = 0, Role.USER =1, Role.GUEST =2을 할당하고 있다.
아무값도 안적어 주면 자동으로 0부터 +1씩 증가한다. 하지만 초기값을 10으로 설정하면 그 이후 차례대로 11,12가 할당되고 두번째 값만 20으로 할당하면 처음부터 0,20,21.. 이렇게 할당되는 모습을 보인다.
+ 문자형으로 할당할 수 있다.
6️⃣ any & unknown타입
any와 unknown 타입 둘다 비슷한 성질을 가지고 있다. 하지만 미세하게 다른데 그 차이점에 대해 알아보겠다.
1. any 타입
특정 변수의 타입을 우리가 확실히 모를때 사용한다.
// any
let anyVar: any = 10;
anyVar = "hello";
anyVar = false;
anyVar = {};
anyVar = () => {};
anyVar.toUpperCase(); //런타임 오류!!
anyVar.toFixed(); //런타임 오류!!
let num: number = 10;
// 타입 좁히기로 any타입을 number타입으로 변경할 수 있음
if (typeof anyVar === "number") {
num = anyVar;
}
num = anyVar;
any타입은 어떤 타입으로든 할당 할 수도 있고 할당 될 수도 있다. 따라서 위에 코드에서 문자열, boolean값, 객체, 함수를 차례대로 대입해도 어떠한 오류가 나타나지 않는다. 마지막에 함수로 할당을 했는데도, toUpperCase()와 toFixed()와 같은 문자열 또는 숫자 타입의 타입만 사용할 수 있는 함수를 선언해도 오류가 발생하지 않는다.
하지만 런타임 실행하면 오류가 발생한다!!
이처럼 런타임에 오류가 발견되면 타입스크립트를 사용하는 이유가 없어진다.
따라서 최대한 any타입을 사용하는 것을 지양하자.
2. unknown 타입
unknown 타입은 any 타입과 비슷하지만 보다 안전한 타입이다.
// unknow
let unKnownVar: unknown;
unKnownVar = "";
unKnownVar = 1;
unKnownVar = () => {};
//unKnownVar.toUpperCase(); // 실행되지 않음
// 정제해서 넣을 수 있음
if (typeof unKnownVar === "number") {
unKnownVar * 2;
}
unknown 타입은 독특하게도 변수의 타입으로 정의되면 모든 값을 할당받을 수 있게 되지만, 반대로 unknown 타입의 값은 그 어떤 타입의 변수에도 할당할 수 없고, 모든 연산에 참가할 수 없게 된다. 쉽게 정리하면 오직 값을 저장하는 행위밖에 할 수 없게 됩니다.
만약 unknown타입을 number타입으로 바꾸고 연산을 하고 싶다면 타입 좁히기를 통해 number타입으로 바꾸고 연산을 해주자.
7️⃣ void & never 타입
1. void 타입
// void
// void -> 공허 -> 아무것도 없다.
// void -> 아무것도 없음을 의미하는 타입
function func1():string{
return "hello"
}
function func2():void{
console.log("hello")
}
let a: void;
a = undefined;
주로 함수에서 쓰이며 return 문이 없을 때 쓰인다. 반환할 값이 없다는 뜻이다.
변수로도 쓰일 수 있으며, 사용할 경우 undefined값 이외에는 다른 값들은 넣을 수 없다.
2. never타입
//never
//never -> 존재하지 않는
//불가능한 타입
function func3():never{
while(true){}
}
function func4():never{
throw new Error();
}
무언가를 반환 할 수 없다는 뜻이다. 위의 코드처럼 while문이 계속 진행되서 반환 할 수 없거나 의도적으로 에러를 발생시킬 때 never 타입이 쓰인다.
'TypeScript' 카테고리의 다른 글
[TypeScript] - 함수 타입 정의하기 (0) | 2023.11.04 |
---|---|
[TypeScript] - 기본다지기2(Complier Option) (0) | 2023.10.28 |
[Typescript] - 기본 다지기(실행 및 설치 방법) (0) | 2023.10.27 |