var 선언자는 기본적으로
Hoisting
의 원리를 따르고 있다. 변수가 선언된 위치와 관계없이scope
의 최상위로 끌어올림 되어 같은 스코프라면 어디서든 호출이 된다. 그러나 할당을 먼저하고 나중에 선언하는 코드는 가독성을 떨어뜨리므로 지양한다. 또한function 레벨 스코프
를 지원하므로 함수내에서 선언한 변수는 함수 내에서만 유효하다. 문제는block 레벨 스코프
를 지원하지 않는다.
//Function Level Scope
var mayName = "cool";
if(true) {
var myName = "happy"
}
console.log(myName); // "happy"
block 레벨 스코프
를 지원하는 대표적인 선언은 다음과 같다
block 레벨 스코프
를 지원하며Hoisting
을 방지한다. ES6의 대표적인 변수 선언에 사용된다.
//Block Level Scope
var mayName = "cool";
if(true) {
let myName = "happy";
}
console.log(myName); // "cool"
let과 마찬가지로
block 레벨 스코프
를 지원하며Hoisting
을 방지한다. ES6의 대표적인 상수 선언에 사용된다. 초기화는 되지만 재할당되지 않는 읽기 전용(readonly) 변수가 된다. 단 const로 선언한 변수라도 객체 리터럴의 속성으로는 변경할 수 있다.
const profile ={
name: "nice",
month: 9
}
const number = 5;
number = 4; // 할당 불가
profile.name = "cool1"; // 할당 가능
profile.month = 8; // 할당 가능
이는 타입스크립트가 속성값의 변경을 허용하는 특성이 있기 때문이다.
언어에 따라 수행하는 타입 검사의 종류
- 정적 타입 검사 (statically type checking) : 실행 전에 타입 검사를 수행하며 Java, C++가 대표적이다.
- 동적 타입 검사 (dynamically type checking) : 실행 중에 타입 검사를 수행하며 Javascript가 대표적이다. (loosely typed) 체계
- 점진적 타입 검사 (gradually type checking) : 타입 검사를 수행하면서 필요에 따라 타입 선언의 생략을 허용한다. 타입 선언을 생략하면 암시적(implicit) 형변환이 일어난다. 타입스크립트에서 점진적 타이핑을 설명할 때 적절한 타입으로 any가 있다. any 타입은 모든 타입의 최상위 타입이며, any 타입으로 선언된 변수는 어떤 타입의 변수도 받아들이면서 심지어 타입이 없는 변수도 받아들인다. TypeScript, Python이 대표적이다. (strong typed) 체계
자바스크립트에는 타입이 추론된다. 이처럼 값을 변수에 할당할 때 타입이 정해지는 것을 동적 타이핑(dynamic typing)이라 한다.
var width = 10;
var myName = "happy";
console.log(typeof myName); //string
console.log(typeof width); //number
기본타입은 보편적으로 많이 사용되는 내장 타입이다.
string, number, boolean, symbol, enum, 문자열 리터럴
Symbol type은 Symbol() 함수를 이용해 생성한 고유하고 수정 불가능한 데이터 타입으로 객체 속성의 식별자로 사용된다.
Symbol을 사용하는 이유 : 객체의 key가 문자열이나 정수일 때의 문제는, 프로그래머의 실수등으로 존재하는 객체의 key 값이 변경될 수 있다. Symbol로 정의할 경우 해당 키는 unique 하기에 중복되지 않는다.
let hello = Symbol("hello");
let hello2 = Symbol("hello");
console.log(hello === hello2); // false
const uniqueKey = Symbol();
let obj = {};
obj[uniqueKey] = 1234;
console.log(obj[uniqueKey]); //1234
console.log(obj); // { [Symbol()]: 1234 }
enum은 number에서 확장된 타입으로 첫 번째 Enum 요소에는 숫자 0 값이 할당된다. (ts 2.4부터는 문자열도 가능)
그 다음 값은 특별히 초기화되지 않는 이상 1씩 증가한다.
enum WeekDay = { Mon, Tue, Wed, Thu }
let day: WeekDay = WeekDay.Mon;
enum을 사용하는 이유 : 코드가 단순해지며 가독성이 좋다. 키워드 enum을 사용하기 때문에 구현의 의도가 열거임을 분명하게 나타낸다.
문자열 리터럴 타입은 string 타입의 확장 타입으로 사용자 정의 타입에 정의한 문자열만 할당받을 수 있다.
type EventType = "keyup" | "mouseover";
객체 타입은 속성을 포함하고 있으며, 호출 시그니처(call signature), 생성자 시그니처(const signature) 등으로 구성된 타입이다.
Array, Tuple, Function, 생성자, Class, Interface
let items: number[] = [1,2,3];
let tuple: [string, number];
tuple = ['hello', 10]; // OK
tuple = [10, 'hello']; // Error
tuple = ['hello', 10, 'world', 100]; // Error
function split(str: string): string[] {
return str.split('');
}
let myFn: (string) => string[] = split;
myFn = function() { }; // Type '() => void' is not assignable to type '(string: any) => string[]'.
메서드 시그니처(method signature)는 메서드의 선언부에 명시되는 매개변수의 리스트를 가리킨다. 만약 두 메서드가 매개변수의 개수와 타입, 그 순서까지 모두 같다면, 이 두 메서드의 시그니처는 같다고 할 수 있다.
관련 조사를 찾던 중 알게 된 TypeScript 팁1!!
TypeScript class constructor Tip!
//이 예제에서는 constructor를 사용하여 기본 클래스에서 공용 속성 position 및 보호 된 속성 speed를 선언한다. 이러한 속성을 매개 변수 속성이라고 한다.
class Car {
public position: number;
protected speed: number;
constructor(position: number, speed: number) {
this.position = position;
this.speed = speed;
}
move() {
this.position += this.speed;
}
}
//TypeScript는 관련 속성에 생성자 매개 변수를 자동으로 할당해준다.
class Car {
constructor(public position: number, protected speed: number) {}
move() {
this.position += this.speed;
}
}
var x: string | number;
interface Cat { leg: number; }
interface Bird { wing: number; }
let birdCat: Cat & Bird = { leg: 4, wing:2 };
void : 빈 값을 나타내는 타입
null, undefined 타입은 다른 모든 타입의 하위 타입(subtype)이다. tsconfig.json에서 strictNullChecks 옵션
을 통해 할당을 방지할 수 있다.
var person = { name: "happy" };
person = null;
console.log(typeof(person)); // object
interface exLookup { ex1: number; ex2: number; ex3: number; }
type useLookup = keyof exLookup;
let real:useLookup = "ex2" // 허용
let type1 = new Boolean(false);
let type2= new Number(123);
let type3= new String("hello world");
type1.valueOf(); type2.valueOf(); type3.valueOf();
책을 보던 중 알게된 JavaScript 팁2!!
==는 값의 비교, ===는 값과 타입 동시에 비교
any
any 타입은 제약이 없는 타입으로 어떤 타입의 값도 받아들일 수 있다. any 의 경우 타입 안정성이 떨어져서 의도치 않는 결과가 나올 수 있고, 그렇다고 한가지 타입으로만 정의하면 지정된 타입 이외에는 다른 타입을 받을 수 없다는 단점이 있다.
noImpicitAny 옵션을 통해 사용을 강제할 수 있따.
-> 나중에 등장하게 될 Generic 사용
object
object 타입은 any타입 처럼 타입 구분 없이 값을 할당할 수 있는 특성이 있어 any 타입과 비슷하다. 그런데 속성 유무를 검사하는 시점이 다르다. any 타입으로 선언한 변수는 속성의 유무를 런타임 시에 검사하지만, object 타입으로 선언한 변수는 컴파일 시간에 속성의 유무를 검사한다. 따라서 object 타입의 변수에 숫자를 할당하더라도 컴파일 시에 숫자 메서드를 인식하지 못하므로 컴파일 시간에 에러가 발생한다. object 타입은 컴파일 과정에서만 유효한 타입이다.
let number = 50;
console.log(typeof number, number.toFixed(1)); // number, 50.0
let number2: Object = 50;
console.log(typeof number2, number2.toFixed(1)); //error 발생
let number3: any = 50;
console.log(typeof number3, number3.toFixed(1)); //number, 50.0
배열 타입은 요소 타입에
[ ]
를 붙여 선언한다.
let myVar: string[] = ["banana","apple"];
제너릭 배열 타입은
Array<T>
형태로 선언한다
let num: Array<number> = [1,2,3];
let num2: typeof num = [4,5,6]; //Type queries
Tuple Type
튜플 타입은 n개의 요소로 이뤄진 배열에 대응하는 타입,
void, null, undefined Type
최고에요 !!!