자바스크립트는
변수의 타입을 미리 지정하지 않아도 자유롭게 사용할 수 있는 동적 언어
개발 속도를 빠르게 해주는 장점도 있지만,
반대로 타입 관련 버그가 런타임에서야 발견될 수 있는 단점이 존재
=> 이런 문제를 해결하고자 나온 것이 바로 타입스크립트(TypeScript)
1. 타입스크립트
- 정적 타입 시스템을 통해 코드를 실행하기 전에 변수의 타입을 정적으로 결정
- 물론 모든 변수에 타입을 지정해야 해서 유연하지 못하다는 단점
타입스크립트는 점진적 타입 시스템을 채택
모든 곳에 타입을 강제로 지정하지 않아도, 타입스크립트가 자동으로 타입을 추론
=> 이를 통해 유연함과 타입 안정성을 모두 가져갈 수 있게 된다.
브라우저나 Node.js가 .ts 파일을 직접 실행할 수 없음
→ 반드시 자바스크립트로 컴파일 후 실행해야 함
2. 타입스크립트 사용법
2-1 프로젝트 초기화
npm init
2-2 타입스크립트와 타입 정의 설치
npm i typescript
npm i @types/node
2-3 타입스크립트 컴파일
tsc src/index.ts
=> 위 명령어를 실행하면 .ts 파일이 .js로 컴파일
2-4 ts-node 사용 (ts 파일을 바로 실행 가능)
npm i -g ts-node
ts-node src/index.ts
=> 현재는 사용이 안됌
npm i -g tsx
=>해당 방식으로 실행해야함
3. 타입스크립트 컴파일러 설정
타입스크립트는 매우 다양한 컴파일 옵션을 제공
아래 명령어로 기본 설정 파일을 생성할 수 있다!!!!
tsc --init
3-1. 컴파일 범위 설정
기존에는 개별 파일을 하나하나 컴파일해야 했으나!
=> include 옵션을 사용하면 여러 파일을 한 번에 컴파일 가능
{ "include": ["src"] }
3-2 자주 사용하는 컴파일러 옵션
{
"compilerOptions": {
"target": "ESNext", // 어떤 버전의 JS로 변환할지
"module": "ESNext", // 사용할 모듈 시스템 (예: ESNext, CommonJS)
"outDir": "dist", // 결과물이 생성될 디렉토리
"strict": false // 타입을 얼마나 엄격하게 검사할지
},
"include": [
"src"
]
}
4. 스코프와 모듈
자바스크립트에서는 각각의 파일이 모듈로 간주!!
타입스크립트에서는 별도로 설정하지 않으면 각 파일이 전역 스코프로 인식
즉, 타입스크립트는 서로 다른 파일에서 동일한 변수명을 사용하면 에러가 발생할 수 있다!!!
- 해결 방법
4-1. export 사용
const a = 1;
export {}; // 이렇게 명시하면 해당 파일은 모듈로 인식됨
4-2. moduleDetection 옵션
{
"compilerOptions": {
"moduleDetection": "force"
}
}
=> 이 옵션을 설정하고 컴파일하면, 아래와 같이 export {}가 자동으로 추가
const a = 1;
export {}; // 자동 추가됨
5. ES Module 관련 설정
다음과 같이 설정: "moduleDetection": "force" // 모듈로 인식하도록 강제
5-1 tsconfig.json
{
"compilerOptions": {
"target": "ESNext", // 최신 JS 문법 사용
"module": "ESNext", // ES 모듈 사용
"outDir": "dist", // 컴파일된 파일이 생성될 디렉터리
"strict": false, // 엄격한 타입 검사 비활성화
"moduleDetection": "force" // 모듈로 인식하도록 강제
},
"include": [
"src"
]
}
=> 이는 package.json에 "type": "module" 설정이 없기 때문!!
5-2 package.json
{
"type": "module"
}
5-3 그런데도 또 오류 발생?
이는 ts-node가 기본적으로 CommonJS 환경에서 실행되기 때문
해결하려면 tsconfig.json에 아래 설정을 추가
{
"ts-node": {
"esm": true
}
}
=> ES 모듈을 제대로 인식하도록 하려면, tsconfig.json 추가 설정
6. 타입 검사 생략 옵션
타입스크립트는 기본적으로 외부 라이브러리의 타입도 검사!!
하지만 아래 옵션을 사용하면 이러한 타입 검사 과정을 생략할 수 있어 컴파일 속도가 향상
{
"compilerOptions": {
"skipLibCheck": true
}
}
=>타입 검사 속도를 높이고, 외부 라이브러리에서 발생하는 타입 오류를 무시
타입스크립트를 처음 접할 때 꼭 알아야 할
기본 타입 개념부터 객체, 튜플, enum, 타입 호환성 정리
7. 타입스크립트 타입
7-1. 기본 타입 (Primitive Types)
타입스크립트에서 기본 타입은 원시 타입으로 불리며, 하나의 값만 저장할 수 있는 타입
- number
- string
- boolean
- null
- undefined
Number
let num1: number = 123;
let num2: number = -123;
let num3: number = 0.123;
let num4: number = -0.123;
let num5: number = Infinity;
let num6: number = -Infinity;
let num7: number = NaN;
num1.toFixed();
// num1 = "hello"; // 오류 발생 //문자에만 쓰는거 안돼!
String
let str1: string = "hello";
let str2: string = "hello";
let str3: string = `hello`;
let str4: string = `hello ${num1}`;
Boolean
let bool1: boolean = true;
let bool2: boolean = false;
Null & Undefined
let null1: null = null;
let unde1: undefined = undefined;
기본적으로 number, string 같은 타입에 null을 넣을 수 없지만!
필요하다면 tsconfig.json 설정을 추가해서사용가능!!!
{
"compilerOptions": {
"strictNullChecks": false
}
}
=> 설정 안하면 strict에 따라서 달라짐
7-2. 리터럴 타입 (Literal Types)
let numA: 10 = 10;
let strA: "hello" = "hello";
let boolA: true = true;
리터럴의 의미 = 값
타입에 값을 집어 넣으면 다른 값이 안됌
7-3. 배열 (Array)
두가지 방식 [] <>제네릭방식
단일 타입 배열
let numArr: number[] = [1, 2, 3];
let strArr: string[] = ["hello", "img"];
let boolArr: Array<boolean> = [true, false];
복합 타입 배열
let multiArr: (number | string)[] = [1, "hello"];
=> 점진적 타입 타입 추론!!! 마우스로 올려보면 타입이 나옴
다차원 배열
let doubleArr: number[][] = [
[1, 2, 3],
[4, 5],
];
7-4. 튜플 (Tuple)
: 타입스크립트만 있는 타입 / 길이가 타입이 고정된 배열
let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, "2", true];
배열 메소드를 사용해도 오류가 나지 않음!! => 주의 필요
tup1.push(1); //타입 안정성 주의 필요!!!
tup1.pop();
tup1.pop();
tup1.pop();
tup1.pop();
튜블도 기본 배열로 인식을 해서 이렇게 사용해서 오류가 안남
그러나 이러면 내가 정한 길이가 문제가 생길 수 있으므로 주의 필요
배열 사용 시 index 위치에 따라 순서가 정해져 있고 중요할 때 값을 안 넣게 방지
const users: [string, number][] = [
["이정환", 1],
["아무", 2],
["김씨", 3],
["박씨", 4],
[5, "호씨씨"],
];
7-5. 객체 (Object)
let user: object = {
id: 1,
name : "이정환"
}
user.id;=> 오류
타입스크립트의 object는 객체인데 잘 모르겠네? 하는 느낌
object를 사용하는게 아니라 객체리터럴을 사용해야함
객체 리터럴 타입
let dog: {
name: string;
color: string;
} = {
name: "돌돌아",
color: "brown",
};
user.id;
: 구조를 기준으로 타입을 지정
=> 구조적 타입 시스템
=> property Based 타입시스템
=> 자바나 c는 명목전 타입 시스템
선택적 프로퍼티
: ?타입이 있어도 되고 없어도 된다
let user: {
id?: number;
name: string;
} = {
id: 1,
name: "이정환",
};
user = {
name: "홍길동동"
}
=> 선택적 프로퍼터 optional 프로퍼티
읽기 전용 프로퍼티
: 프로퍼티의 값을 바꾸는 것을 막아줌 readonly
let config: {
readonly apikey: string;
} = {
apikey: "MY API KEY"
};
config.apikey = "hacked"; // 오류
7-6. 타입 별칭 (Type Alias)
: 타입을 변수처럼 사용 할 수 있는 타입 별칭
type User = {
id: number;
name: string;
nickname: string;
birth: string;
bio: string;
location: string;
};
let user: User = {
id: 1,
name: "홍길동",
nickname: "winterlood",
birth: "1997.01.07",
bio: "안녕하세요",
location: "부천시",
};
조심 할점!! 같은 스코프내 중복된 이름은 안돼~
js에서 타입별칭은 사라짐
7-7. 인덱스 시그니처
type CountryCodes = {
Korea: string;
UnitedState: string;
UnitedKingdom: string;
};
=> 나라가 여러개면 이거 다 쓰라고??안돼!!
key value 의 규칙으로 타입을 정함!!!
type CountryCodes = {
[key: string]: string;
};
let countryCodes: CountryCodes = {
Korea: "ko",
UnitedState: "us",
UnitedKingdom: "uk",
};
인덱스 시그니처는 규칙을 위반만 안하면 괜찮아서
=> 빈 객체도 오류 없게 나옴 주의
type CountryNumberCodes = {
[key: string]: number;
Korea: string; // 오류!
};
=> 두개 value 값은 같아야 한다!!!!
7-8. enum
여러가지 값들이 가각 이름을 열거해두고 사용하는 타입
enum Role {
ADMIN,
USER,
GUEST,
}
enum Language {
korean = "ko",
english = "en",
}
=> 자동으로 0,1,2 할당 가능 지정도 가능
=>USER =10 (숫자형 이넘)을 만들면 0 , 10 , 11 할당
const user1 = {
name: "이정환",
role: Role.ADMIN, //0 관리자자
language: Language.korean,
};
const user2 = {
name: "홍길동",
role: Role.USER, // 1 일반 유저
};
const user3 = {
name: "아무게",
role: Role.GUEST, //2 게스트
};
타입스크립트의 enum 은 type과 다르게 값이 사라지지 않아서
값처럼 사용이 가능하다!! (role: Role.ADMIN)
7-9. any
특정 변수의 타입을 우리가 확실히 모를때
어떤 타입이든지 넣을 수 있음
let anyVar: any = 10;
anyVar = "hello";
anyVar = true;
anyVar = {};
변수 저장도 가능
let num: number = 10;
num = anyVar;
=> 타입 에러는 없지만 실행 시 오류가 떠서 사용 자제!!!!
7-10. unknown
unknown 타입은 any 타입과 비슷하지만 보다 안전한 타입
어떤 타입의 값이든 다 저장
let unknownVar: unknown;
unknownVar = "";
unknownVar = 1;
unknownVar = () => {};
!!!!unknown 타입의 값은 어떤 타입의 변수에도 저장할 수 없다
num = unknownVar; // 오류 !
7-11. void
아무것도 없음을 의미
함수의 반환값 지정이 가능함
function func1(): string {
return "hello";
}
반환값이 없는 경우 함수를 지정 할 때 void를 사용!!!
function func2(): void {
console.log("hello");
}
왜 undefined는 안돼?
함수가 진짜 undefined 을 반환
따라서 return문 자체가 없는 함수의 반환값 타입을 정의해야 할 때에는 void 타입을 이용
7-12 never
불가능한 타입
정상적으로 종료가 안되는 반환이 안되는 함수
function func3(): never {
while (true) {}
}
//모순 에러
function func4(): never {
throw new Error();
}
=> never 타입은 진짜 암것도 못담음
=> strickNullCheck 꺼도 null도 못담음
타입을 정할 때 봐야 하는 것!!!!
어떤 기준으로 타입 정의
어떤 기준으로 타입간의 관계 정의
어떤 기준으로 타입의 오류를 검사하는지
8. 타입 = 집합
타입은 집합!!!!!
여러개의 요소 원소를 하나로 묶어 놓은 것!!!!!!!
동일한 속성과 특성을 모아놓은 집합 = number type
let num:20 =20;
=> 20 1개만 포함하고 있는 집합?
=> 20은 number type 즉 number literal Type 서브타입(자식 타입)
=> number type 슈퍼타입(부모타입)
타입스크립트가 제공하는 여러가지 기본 타입들간의 집합으로써의 부모-자식 관계
타입 호환성!!!!
: 어떤 타입을 다른 타입으로 취급해도 괜찮은지 판단
let num1: number = 10;
let num2: 10 = 10;
num1 = num2; // 업캐스팅
num2 = num1; // 다운캐스팅 //이건 안돼!!!
서브타입의 값을 슈퍼타입으로 취급하는 건 괜찮지만 => 업캐스팅
슈퍼타입을 서브타입으로 보는건 안돼!!!!!!! => 다운캐스팅
- 타입 계층도!!!
8-1 Unknown
전체집합!!! 가장 슈퍼 타입
업캐스팅은 전부 가능 하므로 전체 집합인 unknown은 모든 걸 지정 가능
function unknownExam() {
let a: unknown = 1; // number -> unknown
let b: unknown = "hello"; // string -> unknown
let c: unknown = true; // boolean -> unknown
let d: unknown = null; // null -> unknown
let e: unknown = undefined; // undefined -> unknown
let f: unknown = []; // Array -> unknown
let g: unknown = {}; // Object -> unknown
let h: unknown = () => {}; // Function -> unknown
let unknownValue: unknown;
//다운 캐스팅은 안돼!!!
// let num: number = unknownValue;
// let str: string = unknownValue;
// let bool: boolean = unknownValue;
// 오류 : unknown 타입은 number 타입에 할당할 수 없습니다.
}
8-2 Never 타입
모든 집합의 서브타입 / 모든 집합의 부분집합!!
반환할 수 있는 값이 아무것도 없다!!
=> 공집합
function neverExam() {
function neverFunc(): never {
while (true) {}
}
//업캐스팅으로 가능 never은 모두의 서브집합
let num: number = neverFunc();
let a: number = neverFunc();
let b: string = neverFunc();
let c: boolean = neverFunc();
//다운캐스팅으로 안됌!!
// 그 어느 값도 넣을 수 없음음
// let never1: never = 10;
// let never2: never = "string";
}
8-3 void 타입
void는 undefined의 부모 return 으로 undefined 사용 가능!!
function voidExam() {
function voidFunc(): void {
console.log("hi");
return undefined;
}
let voidVAr: void = undefined;
}
8-4 any 타입
: 치트키 타입
모든 타입의 슈퍼타입으로 위치하기도 하고
모든 타입의 서브타입으로 위치하기도 한다!!(never만 빼공)
function anyExam() {
let unknownVar: unknown;
let anyVar: any;
let undefinedVar: undefined;
let neverVAr: never;
//? 다운캐스팅인데 왜 되는거지?
//=> any는 돼!!!!!!!
//자기 자신이 다운 오키 다른 애들이 다운 오키키
anyVar = unknownVar;
undefinedVar = anyVar;
// neverVAr = anyVar; //오류 never은 순수한 공집합 그 어떤 것도 다운캐스팅 안돼!
}
=> 위험해서 왠만하면 쓰지망
8-5 기본 타입간의 호환성
let num1: number = 10;
let num2: 10 = 10;
//업캐스팅
num1 = num2;
8-6-1 객체 타입간의 호환성
type Animal = {
name: string;
color: string;
};
type Dog = {
name: string;
color: string;
breed: string;
};
let animal: Animal = {
name: "기린",
color: "yellow",
};
let dog: Dog = {
name: "돌돌이",
color: "brown",
breed: "진도",
};
animal = dog;
// dog = animal; //오류!!!!!
객체 또한 기본타입 처럼 서브 슈퍼 타입을 가짐
- 객체도 기본 타입처럼 서브 타입과 슈퍼 타입의 관계를 가짐
- TypeScript는 구조적 타입 시스템
=> 객체의 속성 구조가 기준이 되어 타입 간의 관계를 판단한다.
name과 color 속성이 있는 타입은 Animal이라는 슈퍼 타입
Dog 타입은 name, color에 더해 breed 속성까지 포함하므로 Animal의 서브 타입
더 많은 속성을 가진 타입이 서브 타입, 조건이 더 적은 타입이 슈퍼 타입이 된다.
8-6-2 초과 프로퍼티 검사
실제 작성하지 않은 프로퍼티의 값이 작성되면 막음
딱 객체 타입에 지정된 값만 넣을 수 있음
//슈퍼타입
type Book = {
name: String;
price: number;
};
//서브타입
type ProgrammingBook = {
name: String;
price: number;
skill: string;
};
let book: Book;
let programmingBook: ProgrammingBook = {
name: " 열심히해",
price: 3300,
skill: "react",
};
왜 book = programmingBook;이건되는데 초과프로퍼티 검사로 아래는 안됌
let book2: Book = {
name: " 열심히해",
price: 3300,
// skill: "react", //오류
};
- 객체에 넣지 않아서 가능
let book3: Book = programmingBook;
//객체에 넣은건 아니라 가능ㅋ
- 함수에 인수로 전달 할때도 안돼!!
서브타입 리터럴을 할때는 인수로 전달해!!!!
function func(book: Book) {}
func({
// 오류 발생
name: "한 입 크기로 잘라먹는 리액트",
price: 33000,
// skill: "reactjs",
});
func(programmingBook); //이렇게 인수로 넣는건 ok
'React' 카테고리의 다른 글
React Context API와 LocalStorage로 상태 관리 (0) | 2025.04.23 |
---|---|
Context 알아보기 (0) | 2025.04.22 |
TanStack Query (React Query) 알아보기 (0) | 2025.04.21 |
Axios와 async/await (2) | 2025.04.16 |
React & Next.js 활용해보기 / CSR vs SSR (1) | 2025.04.14 |