타입스크립트 documentation의 Handbook-Everyday Types
Enum
를 참고하였다.
number[]
또는 Array<number>
를 통해 숫자로 구성된 배열을 선언할 수 있다.
[number]
는 number 하나를 원소로 갖는 tuple을 의미한다.
특정 value를 지정하지 않기 위하여 이용된다.
any로 지정된 변수의 어떤 property에도 접근이 가능하며(역시 any
type이 된다), 함수처럼 호출도 가능하고, 아무 타입에 할당하여도 compile error가 발생하지 않는다.
let obj: any = { x: 0 };
// None of the following lines of code will throw compiler errors.
// Using `any` disables all further type checking, and it is assumed
// you know the environment better than TypeScript.
obj.foo();
obj();
obj.bar = 100;
obj = "hello";
const n: number = obj;
타입스크립트는 타입 추론이 불가할 때
any
타입을 이용하게 되는데,noImplicitAny
옵션을 통해 사용자가 직접 명시하지 않은any
에 대해 ERROR를 발생시킬 수 있다.
// Parameter type annotation
function greet(name: string) {
console.log("Hello, " + name.toUpperCase() + "!!");
}
parameter의 type annotation을 추가하지 않으면, argument의 개수가 올바른지만 체크한다.
function getFavoriteNumber(): number {
return 26;
}
보통 타입스크립트가 자동으로 리턴타입을 추론하기 때문에 명시적으로 추가해줄 필요는 없다.
타입스크립트가 파라미터의 타입을 추론할 수 있으면, 파라미터 타입이 자동으로 설정된다.
// No type annotations here, but TypeScript can spot the bug
const names = ["Alice", "Bob", "Eve"];
// Contextual typing for function
names.forEach(function (s) {
console.log(s.toUppercase());
--ERROR : Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});
// Contextual typing also applies to arrow functions
names.forEach((s) => {
console.log(s.toUppercase());
--ERROR: Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});
// The parameter's type annotation is an object type
function printCoord(pt: { x: number; y: number }) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 3, y: 7 });
pt: {x: number; y: number}
와 같은 방식으로 x
와 y
, 두개의 property를 갖는 object를 선언할 수 있다.
각 property를 구분하기 위해서는 ;
또는 ,
를 이용할 수 있다.
property의 타입을 지정하지 않을 수도 있다. 이 경우 property는 any
타입이 된다.
Optional Properties
object의 property가 optional함을 의미하기 위해서는 이름에 ?
를 추가해주자.
function printName(obj: { first: string; last?: string }) {
// ...
}
last
에 접근하면 (possibly) undefined
가 된다. → 접근/이용 전에 undefined
여부를 체크해주도록 하자.여러개의 type들의 합집합. 그 중 하나의 type을 갖게된다.
union type 변수를 이용할 때에는 항상 모든 멤버 타입에 유효하게 동작해야 한다.
예를 들어, string | number
타입인 경우 해당 변수는 string에만 적용 가능한 toUpperCase()
함수는 사용불가하다.
대신 typeof
(또는 Array.isArray()
)를 이용하자.
function printId(id: number | string) {
if (typeof id === "string") {
// In this branch, id is of type 'string'
console.log(id.toUpperCase());
} else {
// Here, id is of type 'number'
console.log(id);
}
}
Type에 object나 Union type을 바로 넣는 대신 새로운 타입을 생성하여 이름을 부여할 수도 있다.
type Point = {
x: number;
y: number;
};
// Exactly the same as the earlier example
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
type ID = number | string
Type Alias는 타입에 이름(별칭)을 부여하는 것이지, 새로운 타입을 생성하는 것이 아니다.
type newString = string;
일때,
newString
으로 타입을 선언하는 것과string
으로 선언하는 것은 완전히 동일하다.
object type에 이름(별칭)을 부여하는 또다른 방법
interface Point {
x: number;
y: number;
}
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
타입스크립트는 항상 값의 shape (또는 structure)를 통해 type을 판단한다는 것을 기억하자. type을 이용하든, interface를 이용하든, shape 가 동일하다면 타입스크립트는 이들을 같은 타입으로 판단한다.
Differences Between Type Alias and Interfaces
interface
에는 새로운 property를 추가할 수 있고,type
는 불가하다.interface Person { name: string } interface Person { age: number } const getPersonInformation = (person: Person) => { console.log(person.name); console.log(person.age) } const person : Person = { name: 'Jujube', age: 25 }; getPersonInformation(person);
위를 인터페이스 병합Merging 이라고 부른다. Merging은 두 선언의 멤버를 같은 이름을 갖는 하나의 interface로 결합시키는 것이다.
type Student = { name: string } type Student = { age: number } // ERROR : Duplicate identifier 'Student'.
Extending in type and interface
interface Animal { name: string } interface Bear extends Animal { honey: boolean } const bear = getBear() bear.name bear.honey
type Animal = { name: string } type Bear = Animal & { honey: Boolean } const bear = getBear(); bear.name; bear.honey;
타입을 좀 더 구체적으로 명시하는 방법
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
그냥 document.getElementById
를 쓰면 Typescript는 HTML element중 하나가 반환된다는 것만 알 수 있지만, 이를 좀 더 구체적으로 명시해줄 수 있다.
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
위의 방식으로 <>
를 이용할 수도 있다.
any
나 unknown
으로 한 번 변환 한 후, 다시 원하는 타입으로 변환하도록 한다. const a = (expr as any) as T;
그냥 일반적인 string
또는 number
타입 대신, 특정 string
이나 number
만을 가질 수 있는 타입을 말한다.
예를 들어, const
를 이용하여 변수를 선언할 때 이러한 리터럴 타입을 이용하게 된다.
보통 Union과 함께 이용된다.
boolean literals
type true
또는 type false
type boolean
은 true | false
유니언 타입의 별칭이다.
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);
위 코드에는
Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.
라는 에러가 뜬다.
req.method
가 string 타입이기 때문.
const req = { url: "https://example.com", method: "GET" as "GET" };
또는
handleRequest(req.url, req.method as "GET");
as const
를 이용하여 객체 전체를 literal 타입으로 변환하는 것이다. 이는 객체의 모든 property에 리터럴 타입의 값이 할당됨을 보장한다.const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);
null
과 undefined
null
과 undefined
는 존재하지 않거나, 초기화되지 않은 값에 이용된다.
strictNullChecks
null
또는 undefined
일 수 있더라도 접근이 가능하다.undefined
또는 null
일 경우를 따로 처리해주어야 한다.!
)null
이나 undefined
가 절대로 아님을 프로그래머가 단언하는 것. 정말로 아닌 경우에만 이용하자.Enums
- Numeric enums
enum Direction { Up = 1, Down, Left, Right, }
enum
키워드를 사용하여 정의한다.Up
이1
로 정의되었고, 뒤의 멤버들의 값은 auto-increment한다!! 신기해!!!!!!
모두 초기화하지 않으면0
부터 시작하여 auto-increment한다. 이용할 때에는Direction.Up
처럼 이용이 가능하다.
- member 값에 추가적인 계산이 필요할 경우 auto-increment가 작용하지 않는다. → 초기화되지 않은 멤버가 계산이 필요한 멤버 뒤에 올 수 없다.
enum E { A = getSomeValue(), B, } -- ERROR : Enum member must have initializer.
- String Enum
각 멤버들은 string literal 또는 또다른 String Enum의 member로 초기화돼야 한다. (auto-increment 기능 없음)enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", }
자주 안쓰이는 primitive~~~
bigint
: number로 표현되지 않는 아주아주 큰 정수
symbol
: 고유한 참조값을 생성한다. Symbol()
를 통해 사용된다. Symbol()
의 argument로 같은 값이 들어가더라도 리턴값은 항상 다른 값 이 된다.
const firstName = Symbol("name");
const secondName = Symbol("name");
if (firstName === secondName) {
This condition will always return 'false' since the types 'typeof firstName' and 'typeof secondName' have no overlap.
// Can't ever happen
}