세 종류의 자바스크립트
자바스크립트는 현재 세 가지 종류가 있다.
es5 : 웹 브라우저에서 동작하는 표준 자바스크립트
esNext : 2015년부터 매년 새로 버전 발표하는 자바스크립트
타입스크립트 : esNext에 타입을 추가
esNext 자바스크립트란?
자바스크립트의 공식 표준은 ECMAScript(ES)이다.
2009년 발표된 ES5 버전이 있는데, 2015년 발표된 ES6 버전에 큰 변화가 있어 ES6 이후 버전을 통틀어 ‘새로운 자바스크립트’라는 뜻에서 ‘ESNext’ 라고 한다.
타입스크립트란?
Microsoft에서 개발한 오픈 소스 언어
자바스크립트의 상위 집합
자바스크립트의 한계를 해결
타입스크립트를 사용하는 이유
타입을 정적으로 선언할 수 있다.
타입 추론를 통한 타입 제어가 가능하다.
컴파일 시점에 오류를 포착할 수 있다.
JavaScript에서 찾을 수 없는 추가 코드 기능을 제공한다.
intellisence 가능하다.
- 생산성 증가
- 규모가 큰 소프트웨어는 여러 명이 유지보수 하기 때문에 유리하다.
동적 타입을 정적으로
자바스크립트에서는 number 값이든, string이든 어떤 타입으로도 할당이 가능하다.
let a;
a = 1;
a = 'b';
하지만 타입스크립트에서는 type annotation으로 number가 선언되면 a에 number값만 할당이 가능하다.
let a : number;
a = 1;
a = 'b'; //Type 'string' is not assignable to tyle 'number' .ts(2322)
타입 추론을 통한 타입 제어
자바스크립트 함수에서는 함수 매개변수와 반환값(return)의 타입을 제어할 수 없었다.
const sum = (a,b) => {
return a+b
}
sum(1,'2') // 12
하지만 타입스크립트에서는 매개변수와 반환 값의 타입을 제어할 수 있다.
const sum = (a: number, b: number) => {
return a+b
}
sum(1, 2) // 3
타입스크립트 원리
컴파일러
대부분의 프로그램이 실행되는 과정이다.
프로그램은 프로그래머가 작성한 다수의 텍스트 파일로 구성된다.
이 텍스트를 컴파일러가 추상 문법 트리(abstract syntax tree, AST) 자료구조로 파싱한다.
컴파일러는 다시 AST를 바이트코드로 변환한다.
바이트 코드가 만들어졌으면 런타임에 의해서 바이트코드를 평가하고 결과를 얻는다.
- 프로그램이 AST로 파싱
- AST가 바이트 코드로 컴파일
- 런타임이 바이트 코드로 평가
타입스크립트에서 컴파일러?
타입스크립트는 컴파일러가 코드를 바이트코드 대신 자바스크립트 코드로 변환한다.
타입스크립트 컴파일러는 AST를 만들어 결과 코드를 내놓기 전에 타입 확인 한다.
TS
1. 타입스크립트 소스 → 타입스크립트 AST
2. 타입 검사기가 AST를 확인
3. 타입스크립트 AST → 자바스크립트 소스
-----------------------------------------------------
JS
4. 자바스크립트 소스 → 자바스크립트 AST
5. AST → 바이트코드
6. 런타임이 바이트코드 평가
추상구문트리(abstract syntax tree)란?
AST는 프로그래밍 언어로 작성된 소스 코드의 추상 구문 구조의 트리이며, 이 트리의 각 노드는 소스코드에서 발생되는 구조를 나타낸다.
쉽게 말하면 우리가 작성한 소스코드를 문법에 맞게 노드들로 쪼개서 만든 트리라고 생각한다.
AST 는 공백, 주석, 탭, 공백 결과를 무시한다.
타입 시스템
타입 시스템이란 타입 검사기가 프로그램에 타입을 할당하는데 사용하는 규칙 집합
타입시스템의 종류
- 명시적으로 타입을 알려주는 시스템
타입 검사기에 타입을 직접적으로 알려주는 시스템
let a: number = 1; //a는 number
let b: string = 'test'; //b는 string
let c: boolean[] = [true, false]; //c는 boolean 배열
- 타입을 추론하는 시스템
명시적으로 사용하지 않으면 타입스크립트가 알아서 타입을 추론한다.
let a = 1; //a는 number
let b = 'test'; //b는 string
let c = [true, false]; //c는 boolean 배열
자바스크립트 vs 타입스크립트
타입 시스템 기능 | 자바스크립트 | 타입스크립트 |
---|---|---|
타입 결정 방식 | 동적 | 정적 |
타입이 자동으로 변환되는가? | O | X(대부분) |
언제 타입을 확인하는가? | 런타임 | 컴파일 타임 |
언제 에러를 검출하는가? | 런타임(대부분) | 컴파일 타임(대부분) |
타입 결정 방식
자바스크립트
프로그램을 실행해야만 특정 데이터의 타입을 알 수 있다.(동적 타입 바인딩(dynamic type binding))
타입스크립트
점진적으로 타입을 확인하는(gradually typed) 언어이다.
즉 타입스크립트는 컴파일 타임에 프로그램의 모든 타입을 알고 있을 때 최상의 결과를 보여줄 수 있지만, 프로그램을 컴파일하는 데 반드시 모든 타입을 알아야 하는 것도 아니다.
타입을 지정하지 않은 프로그램은 일부 타입을 추론해서 오류를 검출할 수 있다.
타입이 자동으로 변환되는가?
자바스크립트
3 + [1]을 타입을 변환하려는 노력으로 3 + [1]을 string 타입인 ‘31’로 변환한다.
타입스크립트
에러난다.
언제 타입을 검사하는가?
자바스크립트
주어진 상황에서 개발자가 무엇을 의도하는지에 맞춰 변환하려 노력할 뿐 대부분의 상황에서 타입이 무엇인지 따지지 않는다.
타입스크립트
컴파일 타임에 코드를 확인하기 때문에 코드를 실행하지 않고도 에러가 있음을 알 수 있다.
에러는 언제 검출되는가?
자바스크립트
런타임에 예외를 던지거나, 암묵적 형변환 수행
타임스크립트
컴파일 타임에 문법 에러와 타입 관련 에러를 모두 검출한다.
IDE에서 타입 체크는 어떻게 하는걸까?
js나 ts로 vscode로 코딩하는 것은 실시간으로 AST를 만드는 것
Visual Studio Code(VSCode)와 같은 코드 편집기에서 JS나 TS로 코딩할 때, 편집기는 실시간으로 코드를 분석하여 AST(Abstract Syntax Tree, 추상 구문 트리)를 생성한다.
TypeScript의 타입 체크는?
TypeScript는 정적 타입 언어로, 코드가 컴파일 시점에 타입을 검사하여 오류를 발견하고 수정할 수 있게 해 준다.
VSCode에서 TypeScript 코드를 작성할 때, 편집기는 백그라운드에서 코드를 지속적으로 분석한다. 이 과정에서 AST(Abstract Syntax Tree, 추상 구문 트리)를 생성하고, 이를 기반으로 타입 검사와 코드 분석을 수행한다.
따라서 개발자가 코드를 입력하는 동안 실시간으로 타입 오류나 문제를 감지하고 경고하거나 수정을 제안할 수 있다.
타입스크립트의 기본 타입
타입스크립트는 자바스크립트 코드에 변수나 함수 등 Type을 정의할 수 있다.
타입을 나타내기 위해서 타입 표기(Type Annotation)를 사용한다.
타입스크립트의 타입 종류
기본 자료형과 참조 자료형은 자바스크립트에서 제공되며 추가 제공 자료형만 타입스크립트에서 추가로 제공되는 타입이다.
기본 자료형(primitive type)
참조 자료형(reference type)
추가 제공 자료형
1. 기본 자료형(primitive type)
object나 reference 형태가 아닌 실제 값을 저장하는 자료형
primitive type 내장 함수를 사용 가능한 것은 자바스크립트 처리 방식 덕분이다.
종류: string, boolean, number, null, undefined, symbol
string
문자열을 저장하는 타입
let str: string = "hi";
Boolean
참/거짓을 저장하는 타입
let isSucceeded: boolean = true;
number
부동 소수 값을 저장하는 타입
2진수, 8진수, 10진수, 16진수 사용 가능
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
null
값이 의도적으로 비어 있는 상태를 저장하는 타입
let n: null = null;
undefined
아무 값이 할당되지 않은 상태를 저장하는 타입
let u: undefined = undefined;
symbol
symbol
타입은 ES6에서 도입된 원시 데이터 타입 중 하나
symbol
타입의 값은 고유하고 수정 불가능한 값으로, 주로 객체 속성의 키로 사용됩니다Symbol()
함수를 호출하여 새로운 심볼 값을 만들 수 있으며, 이 때 각 심볼 값은 유일합니다.
let mySymbol: symbol = Symbol("mySymbolDescription");
2. 참조 자료형(reference type)
객체, 배열, 함수 등과 같은 Object형식의 타입으로 메모리가 값을 주소로 저장하고, 출력 시 메모리 주소와 일치하는 값을 출력한다.
종류: object, array, function
object
기본 자료형에 해당하지 않는 타입
string, boolean, number, null, undefined를 제외한 타임
function create(o: object): void {}
create({ prop: 0 }); // 성공
create([1, 2, 3]); // 성공
create("string"); // error
create(false); // error
create(42); // error
create(null); // error
create(undefined); // error
array
배열을 저장하는 타입
let arr: number[] = [1, 2, 3];
아래와 같이 제네릭을 사용한 타입 표기 가능
let arr: Array<number> = [1, 2, 3];
3. TypeScript 추가 제공 자료형
TypeScript에서 개발자의 편의를 위해 추가로 제공하는 타입
종류: tuple, enum, any, void, never, unknown
tuple
길이와 각 요소의 타입이 정해진 배열을 저장하는 타입
let arr: [string, number] = ["Hi", 6];
arr[1].concat("!"); // string 전용함수인 concat을 사용
// Error, 'number' does not have 'concat'
// 정의하지 않은 index 호출 시 오류
arr[3] = "hello";
// Error, Property '3' does not exist on type '[string, number]'
enum
특정 값(상수)들의 집합을 저장하는 타입
enum Car {
BUS,
TAXI,
SUV,
}
let bus: Car = Car.BUS;
let bus: Car = Car[0]; // 인덱스 번호로 접근
인덱스를 사용자 편의로 변경
enum Car {
BUS = 1,
TAXI = 2,
SUV = 3,
}
let taxi: String = Car[2];
enum Car {
BUS = 2,
TAXI,
SUV,
}
let taxi: String = Car[3];
any
모든 타입을 저장 가능
컴파일 중 타입 검사를 하지 않음
let str: any = "hi";
let num: any = 10;
let arr: any = ["a", 2, true];
void
보통 함수에서 반환 값이 없을 때, any의 반대 타임
변수에는 undefined와 null만 할당하고, 함수에는 반환 값을 설정할 수 없는 타입
let unknown: void = undefined;
function sayHi(): void {
console.log("hi");
}
never
타입은 절대 발생할 수 없는 타입
항상 오류를 발생시키거나 절대 반환하지 않는 반환 타입
종료되지 않는 함수
// never를 반환하는 함수는 함수의 마지막에 도달할 수 없다.
function infiniteLoop(): never {
while (true) {
}
}
// 절대 종료될 일 없는 while문 안에 break가 들어가면 함수가 종료되기 때문에 error가 난다.
function neverEnd(): never {
while (true) {
break;
}
}
// 항상 오류를 발생시키는 함수
function error(message: string): never {
throw new Error(message); // error를 발생시키는 함수 안에 사용가능
}
// 반환 타입이 never로 추론된다.
function fail() {
return error("Something failed");
}
unknown
unknown
은 TypeScript에서 어떤 타입의 값이든 할당할 수 있지만, 해당 값에 대해 구체적인 연산을 수행하기 전에 타입을 명시적으로 검증하거나 좁혀야 하는 안전한 타입입니다.
const def = 123 as unknown as number;
타입 단언 (Type assertions)
타입 단언(Type assertions)이란?
개발자가 TypeScript 컴파일러에게 특정 값의 타입을 명시적으로 알려주는 방법이다.
컴파일러가 타입을 유추할 때 사용하는 정보보다 개발자가 제공하는 정보를 우선시하게 한다.
타입 단언은 컴파일 시점에서만 사용되며, 런타임에는 영향을 주지 않는다.
타입 단언의 두 가지 방식
as
문법을 사용하는 방식
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
- 꺾쇠(
<>
) 문법을 사용하는 방식
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
someValue
는 any
타입으로 선언되었지만, 개발자는 이 변수가 실제로는 string
타입의 값을 가지고 있다고 확신할 수 있다.
따라서 string
타입의 length
속성을 안전하게 사용하기 위해 someValue
를 string
으로 단언한다.
타입 단언을 사용할 때의 주의 사항
개발자가 잘못된 타입을 단언하면, TypeScript 컴파일러는 오류를 감지하지 못하고, 이는 런타임에서 예상치 못한 문제를 일으킬 수 있다.
따라서 타입 단언은 개발자가 해당 변수의 타입을 확실히 알고 있을 때만 사용해야한다.
as unknown as은 왜 동작할까?
타입스크립트 사용을 하면서 as unknown as
를 쓰면 모든(경험상) 타입에러가 해결되는데, 왜 그럴까?
unknown Type
any
타입의 자매처럼 작동한다고 합니다.
any
는 모호한 반면, unknown
는 세부사항이 필요하다. 그래서 as 보다는 더 안전하다고 합니다.
any타입보다 unknown이 안전한 이유
any
타입은 TypeScript에서 타입 체크를 완전히 비활성화합니다.
즉, any
타입의 변수는 어떤 타입의 값이든 받을 수 있고, 해당 변수에 대해 어떠한 연산도 수행할 수 있습니다.
반면, unknown
타입은 보다 안전한 타입으로, 값을 할당할 수는 있지만, 타입을 명확히 지정하지 않는 이상 해당 값에 대해 아무런 연산도 수행할 수 없습니다.
unknown
타입의 변수에 대해 어떤 연산을 수행하려고 하면, TypeScript는 컴파일 타임에 에러를 발생시킵니다. 이는 unknown
타입을 더 엄격하게 다루어야 한다는 것을 의미합니다.
즉, unknown
타입의 변수에 다른 타입의 값을 할당하려면 먼저 타입을 좁혀야 합니다(예: 타입 가드를 사용).
any
에 비해 unknown
은 타입 안전성을 제공하면서, 개발자로 하여금 해당 변수를 사용하기 전에 타입을 확인하도록 강제합니다.
as unknown as
구문이란?
TypeScript에서 타입 단언(Type Assertion)을 사용할 때 쓰이며, 개발자가 TypeScript 컴파일러에게 특정 값의 타입을 명시적으로 지정하도록 요청하는 방법입니다.
이 구문을 사용하면 개발자는 컴파일러에게 "이 타입을 신뢰해, 나는 무엇을 하고 있는지 알고 있다"고 알리는 셈입니다.
예시
const def = 123 as unknown as number;
unknown
은 모든 유형에 할당이 가능하기 때문에, x as unknown
으로 먼저 할당이 가능합니다.
그 다음으로 unknown as y
는 y
에 어떤 타입(string, number 등 모두)이든 다시 unknown
에 할당 할 수 있게 됩니다.
그래서 언제든 as unknown as
는 성공하는 것이다.
이는 TypeScript의 타입 체크 시스템을 일시적으로 우회하는 것으로, 타입 검사를 효과적으로 비활성화합니다.
'타입스크립트' 카테고리의 다른 글
타입스크립트 제네릭 (2) | 2024.03.12 |
---|---|
타입스크립트 interface 인덱서블 타입 (0) | 2024.03.12 |
ts-node로 타입스크립트 파일 바로 실행 (0) | 2024.03.04 |
타입스크립트 declare 사용법 (0) | 2024.03.01 |
타입스크립트 타입 (0) | 2023.08.30 |