1. Java, TypeScript(정적 언어)
컴파일 시점에 타입 결정하고 그때 오류 발견한다.
(JavaScript : 런타임 시점에 타입 오류 확인 가능)
타입 설정하지 않으면 타입스크립트는 any로 설정함.
function add(num1:number, num2:number){
console.log(num1 + num2);
}
add(1,2); // 3
add(); // NaN = undefined + undefined
function showItems(arr:string[]){
arr.forEach((item) => {
console.log(item);
});
}
showItems(['1','2','3']) // 1 2 3
2. 타입 지정
let age:number = 30;
let isAdult:boolean = true;
let a:number[] = [1,2,3];
위랑 동일, let a2:Array<number> = [1,2,3];
let myName:{name : string} = {name : 'kim'};
let myName:string | number = 'kim';
type Member = {
[key :string] : string, // 글자로 된 모든 object 속성의 타입은 : string이다.
}
let john : Member = {name : 'kim'}
//튜플(인덱스 별로 타입 다를 때)
let b:[string, number];
b = ['z', 1];
b[0].toLowerCase();
//void, never
function 함수(x:number) : number { // return 타입 인자 뒤에 : 로 지정
return x*2
}
function sayHello():void{
console.log('hello')
}
never : 에러 던지거나 무한 루프 돌 때 리턴 타입에 선언
//에러 던질 때 보통 never
function showError():never{
throw new Error();
}
//무한 루프 돌 때 never
function infLoop():never{
while(true){
// do something
}
}
//enum(이넘)
enum Os{
Window, //0
ios, //1
android //2
}
Window = 3이라고 하면 ios는 4가되고, android는 5가된다.
let myOs:Os;
라고하면 myOs는 Os에 있는 것만 사용할 수 있다.
myOs = Os.Window 이런 식으로
// 이넘 활용 예제
enum Answer {
Yes = 'Y'
No = 'N',
}
function askQuestion(answer : Answer) {
if(answer ===Answer.Yes) {
console.log('정답입니다.');
}
if(answer ===Answer.No) {
console.log('오답입니다.');
}
askQuestion('예스'); // 오류
askQuestion('y'); // 오류
askQuestion('Yes'); // 오류
askQuestion(Answer.Yes);
}
//null, undefined
let a:null = null;
let b:undefined = undefined;
type vs inteface // 타입과 인터페이스의 차이
1. 타입별칭과 인터페이스의 가장 큰 차이는 확장 가능여부이다.
- 인터페이스는 확장 가능, 타입은 불가능.
3. 객체
// interface
interface User{
name: string;
age: number;
}
let user : User = {
name : 'hahaha',
age: 30
}
console.log(user.age);
//입력해도 되고 안해도 되면 -> ?(Optional)
interface User{
name: string;
age: number;
gender?:string;
}
let user : User = {
name : 'sungjun',
age: 30,
}
user.age =10;
user.gender = "male";
console.log(user.age);
Union Type // 하나 이상의 타입 쓸 수 있게
interface Developer {
name : string;
skill : string;
}
interface Person {
name : string;
age : number;
}
function askSomeone(someone: Developer | Person) {
somone.name ; // 공통된 속성만 사용가능하다.
someone.skill // 불가
someone.age // 불가
}
// InterSection Type
function askSomeone(someone: Developer & Person) {
somone.name ; // 가능
someone.skill // 가능
someone.age // 가능
}
// 읽기 전용이면 변수 앞에 readonly
type Score = 'A' | 'B' | 'C' | 'F';
interface User{
name: string;
age: number;
gender? : string;
readonly birthYear : number;
[grade:number] : Score;
//key를 number로 하고 value를 string으로 하는 것 여러 개 적을 수 있다.
}
interface Add {
//인자 넣고 맨뒤 반환 값 : number
(num1: number, num2: number): number;
}
const add : Add = function(x,y){
return x + y;
}
add(10,20);
interface IsAdult {
(age:number): boolean;
}
//화살표로 함수 표시하기
const a : IsAdult = (age) => {
return age > 19;
}
a(30) //true
//implements
interface Car{
color:string;
wheels:number;
start():void;
}
interface Toy{
name:string;
}
class Bmw implements Car{
color;
wheels = 4;
constructor(c:string){
this.color = c;
}
start(){
console.log('go..');
}
}
const b = new Bmw('green');
console.log(b)
b.start(); //go..
//extends
interface Benz extends Car {
door : number;
stop(): void;
}
const benz : Benz = {
door : 5,
stop(){
console.log('stop');
}
color : 'red',
wheels: 4,
start() {
console.log("START");
}
}
interface ToyCar extends Car, Toy {
price : number;
}
//딕셔너리 패턴
interface StringRegexDictionary {
[key: string]: RegExp;
}
const obj : StringRegexDictionary = {
cssFile: /\.css$/,
jsFile: /\.js$/,
}
obj['cssFile'] = 'a' // 에러
4. 함수 타입
// return type을 인자 뒤에 : 로 표시해주면 된다.
function isAdult(age:number): boolean {
return age > 19;
}
//name은 있어도 되고 없어도 된다. 없으면 world가 나옴.
function hello(name?: string){
return `Hello, ${name || "world"}`;
}
function hello2(name = "world"){
return `Hello, ${name}`;
}
const result = hello();
// 이렇게 선택적 매개변수가 필수 매개변수보다 앞에오면 오류 발생한다.
// 선택적 매개변수는 뒤로 빼야함.
function hello(age?:number, name:string):string {
if (age != undefined) {
return `Hello, ${name}. You are ${age}.`;
} else {
return `Hello, ${name}`;
}
}
//...nums 여러 매개변수, 배열 형태로 나열할 수 있다.
function add(...nums: number[]){
return nums.reduce((result, num) => result + num, 0);
}
add(1,2,3); // 6
add(1,2,3,4,5,6,7,8,9,10); // 55
interface User {
name:string;
}
const Sam: User = {name : 'Sam'}
//this를 사용하는 경우
//매개 변수에 this이렇게 넣어 줘야 한다.
function showName(this:User){
console.log(this.name)
}
const a = showName.bind(Sam);
a();
//오버로드 사용
interface User{
name:string;
age:number;
}
//1st
function join(name:string, age:number):User;
//2nd
function join(name:string, age:string):string;
function join(name:string, age:number | string):User | string{
if(typeof age === "number"){
return {
name,
age,
};
}else{
return "나이는 숫자로 입력해주세요.";
}
}
//1st 예시
const sam:User = join("Sam", 30);
//2nd 예시
const jame:string = join("Jane", "30");
5.Literal Types
//const 변하지 않는 값 선언
//let 변하는 값 선언
//문자열 literal type, Bob이 string으로 변하지 않는값 명시적으로 선언해 놓은 것
const userName1 = "Bob";
//username2는 string type
let userName2 = "Tom";
type Job = "police" | "developer" | "teacher";
interface User {
name: string;
job :Job;
}
const user: User = {
name: "Bob",
job:"developer"
}
console.log(user);
//유니온 타입 = A 또는 B = |
interface Car{
name: "car";
color :string;
start(): void;
}
interface Mobile {
name: "mobile";
color : string;
call():void;
}
function getGift(gift: Car | Mobile){
console.log(gift.color);
if(gift.name ==="car"){
gift.start();
}else{
gift.call();
}
}
//intersaction type ( and 의미)
interface Car{
name: string;
start(): void;
}
interface Mobile {
name: string;
color : string;
price:number;
}
//교차타입의 여러개의 객체를 하나로 합쳐주는 것, 모든 속성을 다 기입해줘야한다.
const toyCar: Toy & Car = {
name: "타요",
start(){},
color : "빨강",
price:1000
}
6. 클래스
//접근 제한자(Access modifier) -
//public - 자식 클래스, 클래스 인스턴스 모두 접근 가능
//private(=#) - 해당 클래스 내부에서만 접근 가능
//protected(자식 클래스 내부에서 사용가능, 클래스 인스턴스에서는 참조 불가능)
class Car {
private color : string; // 자식클래서 내부에서 사용 못한다.
static wheels = 4;
constructor(color:string){
this.color = color;
}
start(){
console.log("start");
console.log(Car.wheels); // 정적 맴버변수는 this가 아니라 클래스를 적어준다.
}
}
const bmw = new Car("red");
class Bmw extends Car {
constructor(color: string) {
super(color);
}
showName(){
console.log(super.name);
}
}
// 추상 class
abstract class Car {
private color : string; // 자식클래서 내부에서 사용 못한다.
static wheels = 4;
constructor(color:string){
this.color = color;
}
start(){
console.log("start");
console.log(Car.wheels); // 정적 맴버변수는 this가 아니라 클래스를 적어준다.
}
}
// 추상클래스는 인스턴스 생성 못함, 상속을 통해서만 이용 가능
const car = new Car("red");
class Bmw extends Car {
constructor(color:string){
super(color);
}
}
7. 제네릭
// Generic
function getStie(arr: number[] | string[] | boolean[] | object[]):number {
return arr.length;
}
const arr1 = [1,2,3];
getSize(arr1); // 3
const arr2 = ["a","b","c"];
getSize(arr2); // 3
const arr3 = [false, true, true];
getSize(arr3); // 3
const arr4 =[{}, {}, {name:"Tim"}];
getSize(arr4); // 3
//이렇게 하는 것 보다 제네릭 사용
function getSize<T>(arr:T[]): number {
return arr.length;
}
const arr1 = [1,2,3];
// 사용하는 쪽에서 타입 지정
getSize<number>(arr1); // 3
const arr2 = ["a","b","c"];
getSize<string>(arr2); // 3
const arr3 = [false, true, true];
getSize<boolean>(arr3); // 3
const arr4 =[{}, {}, {name:"Tim"}];
getSize<Object>(arr4); // 3
interface Mobile<T> {
name : string;
price : number;
option : T;
}
const m1: Mobile<{color : string; coupon: boolean }> = {
name : "s20";
price : 900;
option : {
color : "red",
coupon: false,
},
};
const m2: Mobile<string> = {
name : "s20";
price : 900;
option : "good";
};
// 제네릭의 타입 제한
function logTextLength<T>(text: T[]):T[] {
console.log(text.length);
text.forEach(function (text) {
console.log(text);
});
return text;
}
logTextLength<string>(['hi', 'abc']);
// 제네릭 타입 제한 2 - 정의된 타입 이용하기
interface LengthType {
length : number;
}
function logTextLength<T extends LenthType>(text: T): T {
text.length;
return text;
}
logTextLength(10); // 오류
// 제네릭 타입 제한 3 - keyof로 줄이기 인터페이스의 키만 들어갈 수 있다.
interface ShoppingItem {
name: string;
price: number;
stock: number;
}
function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T):T {
return itemOption;
}
8. 유틸리티 타입
interface User {
id: number;
name: string;
age: number;
gender : "M" | "F";
}
type UserKey = keyof User; // 'id' | 'name' | 'age' | 'gender'
const uk : UserKey = "";
// Partial<T> // 프로퍼티를 모두 optional로 바꿔줌
interface User {
id?: number;
name?: string;
age?: number;
gender? : "M" | "F";
}
let admin:Partial<User> = {
id: 1,
name: "Bob",
}
//Required<T> // 모든 프로퍼티가 필수 값
//Readonly<T> // 읽기만 가능, 수정 불가
//Record<K,T> // K : 키, T : 타입
type Grade = "1"| "2"| "3"| "4"| "5" ;
type Score = "A"| "B"| "C"| "D"| "E" ;
const score = Record<Grade, Score> = {
1: "A",
2: "B",
3: "C",
4: "D",
5: "E",
};
function isValid(user:User){
const result = Record<keyof User, boolean> = {
id: user.id > 0,
name : user.name !="",
age : user.age > 0,
};
return result;
}
//Pick 객체에서 특정 프로퍼티만 꺼내서 사용
//Omit 특정 프로퍼티 생략해서 사용 가능
//Exclued<T1,T2> : T1타입 중에서 T2타입에 겹치는 것 제외 함
const admin : Pick<User, "id" | "name">= {
id: 0,
name : "Bob",
};
type T1 = string | number | boolean;
type T2 = Exlcude<T1, number | string;
//NonNullable<Type> // Null을 제외한 타입 제거( null, undefinded )
type T1 = string | null | undefined | void;
type T2 = NonNullable<T1>; // string, void만 남음
https://joshua1988.github.io/ts