본격적인 타입스크립트 기초 문법 실습에 앞서 Type Annotation 개념에 대해 설명드리겠습니다.

1)Type Annotation 이해하기
Annotation은 주석이라고 해석되며 사전적 의미는 어려운 낱말이나 문장을 쉽게 풀이한것을 뜻하지만
타입스크립트에서의 Type Annotation은 변수,함수,객체 속성의 데이터 타입을 지정하는 행위를 말합니다.

A)Type Annotation 기초 사용법
-변수명, 함수명, 객체 속성명 뒤에 : type 을 써서 데이터 타입을 지정하는 것을 Type Annotation 이라고합니다.

예시)
let age:number;

-type 형태는 자바스크립트의 원시타입primitive type(number, string, boolean)이나 객체,클래스,인터페이스,개발자 정의 타입,함수등을 대표적으로 사용가능합니다.
-Type annotation을 사용하여 type 검사를 수행하여 잠재적 에러를 확인할수 있습니다.
-Type Annotation 지정은 필수사항은 아니지만 아래와 같은 장점을 제공하기 때문에 그 사용을 권장합니다.

B)Type Annotation사용 시 장점
-타입스크립트 컴파일러가 type을 확인하여 빌드타임 타입체크 및  에러 확인기능 제공
-data type을 처리시  사전 오류 방지에 도움
-팀 협업을 할 때 동일 타입을 공유할수 있어 코딩컨벤션(코딩규칙) 제공 편리한 팀협업 제공
-타입을 공통 모듈로 관리 유지보수 편리 

C)TypeScript 유형별 Type 학습하기
-원시 데이터 타입: string,number,boolean,null,undefined,symbol
-참조 타입: 배열(Array []),튜플 (tuple),객체(object),함수(Function),클래스(Class)
-기타 타입: Void,Never,Any,Type Assertion(어써선 as),Union(타입결합):TypeAlias(개발자타입정의),Literal,열거형(enum):

D)Type별 기초 설명 및 사용법 링크)
https://typescript-kr.github.io/pages/basic-types.html
 
** 중요: 타입스크립트 기본 타입 유형별 실습/코딩이 필요하신분들은 위에 기초 타입 유형별 링크를 참고해 아래 TS Playground 웹사이트에서 직접 실습을 진행해보시기 바랍니다.

Tip) 온라인에서 타입스크립트 코딩 연습하기
- 온라인상에서 웹브라우저기반 타입스크립트 코딩연습을 위한 TS Playground 문법 연습 REPL툴 사이트를 아래와 같이 제공합니다.
https://www.typescriptlang.org/play
 
-REPL(Read-Eval-Print Loop) 툴이란 사용자가 입력한 코드를 읽어서(Read) 평가(Eval)하고 그 결과를 출력(Print)한 후 다시 입력을 기다리는(Loop) 동작을 반복하는 프로그래밍 환경
-REPL은 즉시 코드를 실행하고 결과를 확인할 수 있어, 새로운 언어를 배우거나 코드 스니펫을 테스트하는 데 유용합니다.
-Python, Node.js, Ruby 등 많은 언어가 REPL 환경을 제공하며, 웹 기반 REPL 환경도 많이 제공됩니다.


2) 변수(Variable) Type 실습
VSCode의 작업 폴더내에 2-TS-Basic폴더를 추가하고 해당 폴더로 이동하고 variables.ts파일을 생성 합니다.

D:\TypeScript\2-TS-Basic
cd 2-TS-Basic
D:\TypeScript\2-TS-Basic

A) 변수(Variable) Type 코딩하고 실행하기
-variable.ts

하기 코드와 같이 코딩을 진행합니다.
** 타입스크립트 코딩이 처음이신분들은 직접 코딩을 진행해보세요.
-자세한 내용은 주석을 참고바랍니다.

//변수별 타입을 지정하고 값을 할당합니다.
var memberName: string = "강창훈";
let age: number = 40;
let price: number = 5000;
const isMale: boolean = true;

let totalPayPrice: number = 0;

//함수가 반환값이 없을때는 함수명():void{}
//함수에 전달되는 파라메터(매개변수)에도 타입을 지정합니다.
//함수의 결과값에는 void값을 할당합니다.
function showTotalPrice(price: number, count: number): void {
  totalPayPrice = price * count;
  console.log("총 금액은 " + totalPayPrice + "원 입니다.");
}

console.log("사용자명:", memberName);
console.log("성별:", isMale);
showTotalPrice(price, 2);

//컴파일 및 실행 명령어
//tsc --strictNullChecks type-variable.ts
//node type-variable.js


-코딩을 모두 진행 저장하고 아래 명령어를 통해 터미널창에서 ts파일을 컴파일하고 컴파일 결과.js파일을 실행합니다.
D:\TypeScript\2-TS-Basic
tsc --strictNullChecks variable.ts
node variable.js


B)코딩 핵심 내용 설명
-변수값의 유형별로 어떤 원시타입을 지정했는지 확인합니다.
-함수에 전달되는 파라메터 변수를 매개변수라고 합니다.
-함수내에 값을 전달할때 사용하는 매개변수(파라메터)들에도 타입을 지정할수 있습니다.
-함수의 결과값도 타입을 지정할수 있으며 결과값이 없으면 void를 지정합니다. 


3) 타입추론(Types by Inference) 이해 및 실습
D:\TypeScript\2-TS-Basic 폴더내에 type-inference.ts파일을 생성 합니다.

A) 타입추론 예시코드 코딩하고 실행하기
-하기 코드와 같이 코딩을 진행합니다.
-자세한 내용은 주석을 참고바랍니다.
-type-inference.ts
** 에러확인을 위해 에러코드예시의 주석을 해제하고 실행하세요.

//Case1)변수 타입추론 개념 이해하기
//변수의 타입을 지정하지 않아도 값을 명시적으로 할당하면 타입 추론에 의해 타입이 결정됩니다.
var memberName = "강창훈";
var price = 5000;
var isMale = true;

//price의 값을 5000 숫자형으로 명시적 할당했기 떄문에 타입스크립트는 타입추론에 의해 숫자로 자동인식함

console.log("회원명은 타입추론에 의해 문자로 자동 인식:", memberName.length);

//에러코드예시: 아래 문자열 타입에서만 제공하는 length속성이나 substring 함수는 숫자 속성에서는 타입에러를 발생시킴
//console.log("가격은 타입추론에 의해숫자 로 자동 인식:", price.length);
//console.log("가격은 타입추론에 의해숫자 로 자동 인식:", price.substring(0, 2));
//console.log("성별은 타입추론에 의해 불린형으 로 자동 인식:", isMale.length);

//Case2)객체 타입추론 개념 이해하기
//객체의 속성 타입을 지정하지 않고 값을 명시적으로 할당하면 객체 속성의 타입도 타입추론에 의해결정됨
var user = {
  id: 1,
  name: "John Doe",
  email: "john.doe@example.com",
};

console.log("회원명은 타입추론에 의해 문자로 자동 인식:", user.name.length);

//에러코드예시:아래코드는 타입에러 발생 id는 숫자형인데 숫자형 length속성이 없어서 발생
//console.log("회원아이디는 타입추론에 의해숫자 로 자동 인식:", user.id.length);

//Case2)함수의 매개변수를 타입지정한 경우 반환값 타입을 지정하지 않아도 결과값을 타입추론하여 숫자형으로 결정함
//함수의 매개변수는 타입추론이 불가하다.
function plus(a: number, b: number) {
  return a + b;
}
//함수의 반환값이 숫자형이므로 length 속성을 사용할 수 없음
console.log(plus(1, 2));

//에러코드예시:함수결과값 타입을 지정하지 않으면 타입추론이 되어 에러발생
//console.log(plus(1, 2).length);

//컴파일 및 실행 명령어
//tsc --strictNullChecks type-inference.ts
//node type-inference.js


-코딩을 모두 진행 저장하고 아래 명령어를 통해 터미널창에서 ts파일을 컴파일하고 컴파일 결과.js파일을 실행합니다.
D:\TypeScript\2-TS-Basic
tsc --strictNullChecks type-inference.ts
node type-inference.js

B)코딩 핵심 내용 설명
-함수의 매개변수를 타입지정한 경우 반환값 타입을 지정하지 않아도 결과값을 타입추론하여 숫자형으로 결정함
-함수의 매개변수는 타입추론이 불가하다.



4) Type Assertion(어써선=단언/역설)과 any타입 사용하기

Assertion 이란 용어는 단언하다,확고히 말하다(역설)의  의미를 내포하는데요.
Type Assertion은 개발자가 해당 타입에 대해 정확한 확신이 있을 때 사용하는 타입 지정 방식으로  타입스크립트 컴파일러에게 이 값은 반드시 이런 타입이여해,이런 타입일거야 하고
컴파일러에게 알려주고 타입형을 변환하는 용도로 사용합니다. 
Type Assertion으로 지정되는 값은 컴파일러가 타입체크를 하지않고 데이터의 구조도 신경쓰지 않습니다.

주로 타입스크립트의 타입 캐스팅(타입형변환)시 사용합니다.
타입 단언은 타입스크립트 컴파일러보다 개발자가 더 해당 타입을 잘 알고 있을 때 사용합니다.
Type Assertion은 타입의 형을 변환할때 사용하는 방법으로 as키워드를 사용하거나 angle-bracket <타입> 문법을 사용해 구현할수 있습니다.

D:\TypeScript\2-TS-Basic 폴더내에 type-assertion.ts파일을 생성 합니다.

A) Type Assertion 예시코드 코딩하고 실행하기
-하기 코드와 같이 코딩을 진행합니다.
-자세한 내용은 주석을 참고바랍니다.
-type-assertion.ts

//Case1)타입 어서션 개념 이해하기
//any타입은 타입이 어떤 타입인지 정확히 모를때 저정할수 있는 타입을 말합니다.
//프론트/백엔드 ,외부시스템, 타팀이 만든 결과 데이터를 받을때 정확한 타입을 모를때 사용합니다.
//타입스크립트 기반 애플리케이션을 개발하면서 any타입을 남발하는것은 좋지 않습니다.

//any타입으로 정의된 변수는 데이터 타입을 변경해 값을 할당해도 문제가 되지 않는다.
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false;

console.log("notSure", notSure);

let fullName: any = "Eddy.Kang";

//타입 어서션 방법1: as키워드 사용
//any 타입인 fullName을 문자열 타입으로 변환하는 방법1 : fullName as string
let fullNameLength1: number = (fullName as string).length;

//타입 어서션 방법2: angle-bracket 문법 사용 (<타입>변수)
//any 타입인 fullName을 문자열 타입으로 변환하는 방법2 : <string>fullName
let fullNameLength2: number = (<string>fullName).length;

const companyName = "MSoftware" as string;
console.log("companyName===>", fullNameLength1, fullNameLength2, companyName);

//User Interface정의
interface User {
  id: number;
  name: string;
  email: string;
  telephone?: string; //선택적(옵셔널) 속성은 속성명?로 정의
}

//사용자 객체변수/타입 정의 및 값 할당
//선택적(옵셔널) 속성은 반드시 값을 할당하지 않아도 됨.
let user = {} as User;
user.id = 1;
user.name = "Eddy.Kange";

console.log("user===>", user);

//컴파일 및 실행 명령어
//tsc --strictNullChecks type-assertion.ts
//node type-assertion.js


-코딩을 모두 진행 저장하고 아래 명령어를 통해 터미널창에서 ts파일을 컴파일하고 컴파일 결과.js파일을 실행합니다.
D:\TypeScript\2-TS-Basic
tsc --strictNullChecks type-assertion.ts
node type-assertion.js

B)코딩 핵심 내용 설명
-any타입은 타입이 어떤 타입인지 정확히 모를때 저정할수 있는 타입을 말합니다.
-any타입은 프론트/백엔드 ,외부시스템, 타팀이 만든 결과 데이터를 받을때 정확한 타입을 모를때 사용합니다.
-타입스크립트 기반 애플리케이션을 개발하면서 any타입을 남발하는것은 좋지 않습니다.


5) 여러 타입으로 타입정의하고 값 제한하기- Union Type
타입스크립트는 기존의 타입들을 이용해 새로운 타입을 정의하고 구성하는 방법을 제공합니다.
새로운 타입을 재구성하는 방식으로는 Union과 Generic 방식 두가지를 제공합니다.

이번시간에는 Union에 대해서만 다루고 다른섹션에서 Generic에 대해 다루겠습니다.
Union은 타입이 여러 타입 중 하나일 수 있음을 선언하는 방법으로 하나의 변수에 여러타입을 지정할수 있습니다.
let productCode: string | number;

예제 코드처럼 | 문자를 이용해 여러 타입을 반복지정 가능합니다.

D:\TypeScript\2-TS-Basic 폴더내에 type-union.ts파일을 생성 합니다.

A) UnionType 예시코드 코딩하고 실행하기
-하기 코드와 같이 코딩을 진행합니다.
-자세한 내용은 주석을 참고바랍니다.
-type-union.ts

-코딩을 모두 진행 저장하고 아래 명령어를 통해 터미널창에서 ts파일을 컴파일하고 컴파일 결과.js파일을 실행합니다.
D:\TypeScript\2-TS-Basic
tsc --strictNullChecks type-union.ts
node type-union.js

// Union 타입 예제

//productCode 변수에 문자열과 숫자 타입 2개 타입을 동시에 지정합니다.
let productCode: string | number = "10000";

productCode = 20000;
console.log("productCode===>", productCode);

productCode = "P-20000";
console.log("productCode===>", productCode);

//함수에 유니온 타입 지정하기
function getCode(code: number | string): string {
  if (typeof code === "number") {
    code = "P-" + code.toString();
  }
  return code;
}

console.log("getCode:", getCode(1000));
console.log("getCode:", getCode("P-2000"));

//두번쨰 예시..
function getProductCode(pcode: string | number): void {
  if (typeof pcode === "string") {
    console.log(`문자열값: ${pcode}`);
  } else if (typeof pcode === "number") {
    console.log(`숫자형값: ${pcode}`);
  }
}

console.log("getProductCode:", getProductCode("PID-1000"));
console.log("getProductCode:", getProductCode("1000"));

//배열내에 여러 데이터 유형을 할당하고 해당 배열의 타입을 Union타입으로 정의할수 있습니다.
const userData: (string | number | boolean)[] = ["홍길동2", 40, false]; //Union Type

console.log(
  `${userData[0]} 님은 ${userData[1]}살이고 ${
    userData[2] == true ? "기혼" : "미혼"
  } 입니다.`
);

//Union 타입을 이용해 타입의 특정값만을 지정할수 있습니다.
//Enum(열거형) 타입과 유사하게 특정값만을 지정할수 있습니다.
type ProcessStates = "open" | "closed";
let state: ProcessStates = "open";
console.log("state:", state);

type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
let oddNumber: OddNumbersUnderTen = 3;
console.log("oddNumber:", oddNumber);

//컴파일 및 실행 명령어
//tsc --strictNullChecks type-union.ts
//node type-union.js


B)코딩 핵심 내용 설명
-union을 이용하면 변수에 여러타입을 지정할수 있습니다.
-배열내 여러 타입의 값을 담을수도 있습니다.
-추후배울 type alias에 여러값을 할당할수 있습니다.
-유니온 타입에 특정 값들을 설정해 변수의 갑을 지정된 값들로 제한하는 기능도 제공한다.
(Enum열거형 타입과 동일기능제공 )


6)Type Alias
타입스크립트에서는 개발자 정의 타입을 정의해서 새로운 타입을 만들어 사용할수도 있습니다.
type키워들을 이용해 새로운 타입을 정의하고 변수나 객체,함수등에 적용가능합니다. 

D:\TypeScript\2-TS-Basic 폴더내에 type-alias.ts파일을 생성 합니다.

A)Type Alias 예시코드 코딩하고 실행하기
-하기 코드와 같이 코딩을 진행합니다.
-자세한 내용은 주석을 참고바랍니다.
-type-alias.ts

//Case1)타입 별칭을 사용하여 두가지 타입을 지원하는 새로운 타입을 정의합니다.
type StringOrNumber = string | number;
let sample: StringOrNumber;
sample = "hello";
console.log("sample:", sample);

sample = 123;
console.log("sample:", sample);

//Case2)복잡한 타입도 별칭으로 정의할 수 있습니다.
//MemberType 타입 별칭 구조와 속성 타입을 정의합니다.
type MemberType = {
  name: string;
  age: number;
  address: { city: string; country: string };
};

//해당 MemberType 타입의 변수를 선언하고 값을 할당합니다.
let personData: MemberType = {
  name: "John Doe",
  age: 25,
  address: {
    city: "Seoul",
    country: "South Korea",
  },
};

//특정함수에 파라메터로
function printPersonInfo(person: MemberType) {
  console.log(
    `name: ${person.name}, age: ${person.age}, address: ${person.address.city}, ${person.address.country}`
  );
}

printPersonInfo(personData);

//Case3)함수의 구조를 타입으로 정의하기
//마이너스함수를 타입으로 minusFunc 타입으로 정의함
//calFunc()함수의 구조를 타입으로 정의한다.
//type 함수타입명 =(파라메터)=>반환값타입
type calFuncType = (a: number, b: number) => number;

function plus(a: number, b: number) {
  return a + b;
}

function minus(a: number, b: number): number {
  return a - b;
}

//함수의 파라메터로 특정함수를 전달할때는 전달 함수의 파라메터명:(함수 파라메터명:타입,파라메터명:타입) => 함수반환타입 형식으로 정의
//calculate()함수에 파라메터(인수)로 전달되는 함수의 파라메터명과 타입,반환값을 어떻게 정의하는지 확인하세요.
//여러개의 기초함수를 만들어두고 해당 기초함수의 공통함수타입을 정의후 특정함수에 파라메터로 전달해 하나의 함수를 통해 선택적으로 매개변수함수를 실행할수있다.
function calculate(a: number, b: number, calFunc: calFuncType): number {
  return calFunc(a, b);
}

//calculate함수에 plus,minus 함수를 파라메터로 전달해 해당 전달함수의 로직으로 계산을 수행하게 하는 예시
console.log(calculate(10, 5, plus));
console.log(calculate(10, 5, minus));

//CaSe4: 함수 파라메터인수와 반환값을 위한 type 정의
type OperationInput = {
  a: number;
  b: number;
};

type OperationOutput = {
  result: number;
};

// 함수 구현
function addNumbers(input: OperationInput): OperationOutput {
  const { a, b } = input;
  return { result: a + b };
}

// 사용 예시
const input: OperationInput = { a: 5, b: 3 };
const output: OperationOutput = addNumbers(input);
console.log(output); // { result: 8 }

//tsc --strictNullChecks type-alias.ts
//node type-alias.js


-코딩을 모두 진행 저장하고 아래 명령어를 통해 터미널창에서 ts파일을 컴파일하고 컴파일 결과.js파일을 실행합니다.
D:\TypeScript\2-TS-Basic
tsc --strictNullChecks type-alias.ts
node type-alias.js

B)코딩 핵심 내용 설명
-단일 타입에 여러 타입지원을 위해 Union을 통해 정의할수 있습니다.
-복잡한 객체의 구조도 별도 타입으로 정의할수 있습니다.
-함수의 구조도 타입으로 정의해서 사용할수 있습니다.
-자바스크립트 함수는 함수의 매개변수로 특정함수를 전달할수 있다.
-함수의 매개변수로 전달되는 함수의 타입을 함수타입으로 정의해 사용할수 있다


7)Literal & Enum Type & Union Type
Literal Type과 Enum Type 데이터의 집합을 표현하는 타입니다.
Literal Type변수나 Enum(열거형) Type은  미리 정해진 문자열값 들이나 숫자값들을 미리 정의해두고 해당 범위내의 값들만을 사용할수있게 강제하는 기능을 기본 제공합니다.
Enum 타입은 열거형이라고 말하며 enum이라는 키워드를 사용해  여러개의 상수셋을 정의해 구현합니다. 

D:\TypeScript\2-TS-Basic 폴더내에 type-literal-enum.ts파일을 생성 합니다.

A)Type Alias 예시코드 코딩하고 실행하기
-하기 코드와 같이 코딩을 진행합니다.
-자세한 내용은 주석을 참고바랍니다.
-literal-enum.ts

-코딩을 모두 진행 저장하고 아래 명령어를 통해 터미널창에서 ts파일을 컴파일하고 컴파일 결과.js파일을 실행합니다.
D:\TypeScript\2-TS-Basic
tsc --strictNullChecks type-literal-enum.ts
node type-literal-enum.js

//Case1)변수 값으로 문자열 Literal Type 사용하기
let genderType: "Male" | "Female";

genderType = "Male";
console.log("genderType:", genderType);

genderType = "Female";
console.log("genderType:", genderType);
//genderType = "None"; // 스트링 리터널 타입에서 사전 정의된 값이 아니여서 에러발생

type User = {
  name: string;
  age: number;
  userType: "admin" | "user";
  address: { city: string; country: string };
};

const user: User = {
  name: "John Doe",
  age: 25,
  userType: "admin",
  address: {
    city: "Seoul",
    country: "South Korea",
  },
};

//Case2)함수의 반환값으로 숫자형 Literal Type 사용하기
function getUserType(user: User): 1 | 2 {
  if (user.userType === "admin") {
    return 1;
  } else {
    return 2;
  }
}

console.log("getUserType:", getUserType(user)); //1

//Case3)열거형(Enum) 타입

//게시글 게시 상태코드 열거형
enum DisplayType {
  NoneDisplay = 0,
  Display = 1,
}

const displayCode = 1;
const display = displayCode as DisplayType;

if (display === DisplayType.Display) {
  console.log("해당 게시글은 게시상태입니다.");
}

//SNS 타입 열거형
enum SNSType {
  None = "",
  Facebook = "facebook",
  Instagram = "instagram",
  Twitter = "twitter",
}

//회원가입 상태 타입 열거형
//상수값을 지정하지 않으면 0부터 시작하는 숫자값이 할당됩니다.
enum EntryStatus {
  Inactive, //0
  Active, //1
  Pending, //2
}

//회원 유형 타입 열거형
enum MemberType {
  Admin = 2,
  User = 1,
  Guest = 0,
}

type Member = {
  id: number;
  email: string;
  password: string;
  entryStatus: EntryStatus;
  memberType: MemberType;
  snsType: SNSType;
  address: { city: string; country: string };
};

const snsTypeCode = "Facebook";

//해당 MemberType 타입의 변수를 선언하고 값을 할당합니다.
let member: Member = {
  id: 1,
  email: "test@test.co.kr",
  password: "dfdfdfd23sdsdsds..",
  memberType: MemberType.Admin,
  snsType: snsTypeCode as SNSType,
  entryStatus: EntryStatus.Pending,
  address: {
    city: "Seoul",
    country: "South Korea",
  },
};

console.log("member:", member);

//Case4:Union 타입을 이용해 타입의 특정값만을 지정할수 있습니다.
//Enum(열거형) 타입과 유사하게 특정값만을 지정할수 있습니다.
type ProcessStates = "open" | "closed";
let state: ProcessStates = "open";
console.log("state:", state);

type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
let oddNumber: OddNumbersUnderTen = 3;
console.log("oddNumber:", oddNumber);

//tsc --strictNullChecks type-literal-enum.ts
//node type-literal-enum.js


B)코딩 핵심 내용 설명

-Literal Type은 문자열,숫자형 리터널 타입이 존재합니다.
-Enum Type(열거형타입)은 enum으로 선언하고 여러개의 상수셋을 정의해 구현합니다.
-Enum Type 대신 Union 타입을 통해 특정값 범위를 제한할수도 있습니다.
-열거형 상수에 값을 할당하지 않으면 숫자형 값이 순차적으로 0부터 할당됩니다.


지금까지 타입스크립트의 주요 기본개념과 주요타입선언 방식을 배워보았습니다.
직접 코딩을 통해 사용법이 손에 익고 머리로 이해가 될때까지 충분한 코딩 문법에 익숙해지도록 노력해보세요.

오늘도 수고 많으셨습니다.