JavaScript의 상위로, 오류 가능성이 높은 JS를 컴파일 단에서 잘 잡기 위해서 만들어졌다.
문법이 엄격하여 사전에 오류 진단이 가능하다.
런타임 오류 => 컴파일 오류 로 바뀌는 경우가 많다.
npm 설치 후
npm init
npm add -D typescript
로 설치
tsconfig.json을
{
"compilerOptions": {
"target": "ES2022",
"rootDir": "./src",
"outDir": "./dist",
"strict": true
},
"include": ["src/**/*.ts"]
}
로 하면, ./src 밑의 ts 구조를 ./dist 밑의 js 구조로 바꾸겠다는 것이다.
예시로
src/tmp.ts
src/asdf/tmp.ts
=>
dist/tmp.js
dist/asdf/tmp.ts
로 된다는 것이다.
pnpm exec tsc
로 컴파일 하면 ./dist에 생긴다
node 파일명
으로 컴파일된 js 실행 가능하다
vscode의 ts 확장 깔면 약간 문제 생길 가능성 있다
우선, ts는 변수의 타입을 여러 번 선언할 수 없다
연습하다보면 변수명이 자주 겹치는데,
이 문제는 ts 파일 밑에 export {};를 붙여서 해결 가능하다
모듈화를 해서 각각의 공간만 이용한다는 뜻이다.
이 경우, export {}; 가 오류가 날 수 있는데,
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"moduleDetection": "force",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
}
}
로 모듈 moduleDetection force가 각 파일을 모듈로 처리한다는 말로,
예제 풀기 좋은 환경을 만들 수 있다.
추가적으로, 파일 자동 포멧 생성이랑 컴파일이 귀찮아서 chatGPT 도움 받아서 자동 기능 만들었다.
https://github.com/kysth0707/ezts
vscode가 .vscode 인식을 가끔 못할 때는 tasks.json을 새로 저장하면 된다.
#1. print
/*
* 제목 : print
*
* < 요약 >
* python과 비슷함
* +로 할 수 있으나, python의 fstring처럼 ${}로 내부에 작성 가능
* 그러나, `(하이픈, ~에 있는 친구)를 써야함
*
* [2026/09/16 11:22:09]
*/
const courseName = "TypeScript";
console.log("이번 주 학습 주제: " + courseName);
console.log(`이번 주 학습 주제: ${courseName}`);
export {};
#2. type 오류 찾기
/*
* 제목 : 오류찾기
*
* < 요약 >
* type 안 맞게 하면 오류
*
* [2026/09/17 00:29:36]
*/
// Before
/*function introduceStudent(studentName: string, currentLevel: number) {
return studentName + " 님은 현재 " + currentLevel + "레벨이에요.";
}
introduceStudent("광수", "1");*/
// After
function introduceStudent(studentName: string, currentLevel: number) {
return studentName + " 님은 현재 " + currentLevel + "레벨이에요.";
}
introduceStudent("광수", 1);
export {};
#3. 원시 값, 객체 값, 타입 선언
/*
* 제목 : 원시 값, 객체 값, 타입 선언
*
* < 요약 >
* 원시 값은 value 비교, 객체 값은 주소 비교
* 그래서 lodash 같은 deep 비교 필요
* import _ from 'lodash';
* console.log(_.isEqual(objA, objB));
*
* array라고 하지만 list(dynamic array)임.
* [] 꼴로 리스트 자주 작성. var는 scope 탈출해서 안 씀.
*
* [2026/09/17 00:32:16]
*/
// 1
const firstMember = { name: "광수" };
const secondMember = { name: "광수" };
const sameMember = firstMember;
console.log(firstMember === secondMember); // false {}로 객체임
console.log(firstMember === sameMember); // true
//2
let a = '123'; // 알아서 string
let b = 123; // 알아서 number
let c: string = '123'; //내가 지정
//3
const tmp: string[] = ["ㅇ"];
tmp.push("ㅎㅇ요"); //const 라고 쓸 수 없는 게 아님. 주소가 고정.
const tmp2: readonly string[] = ["ㅇ"];
// tmp2.push("ㅎㅇ"); //오류남
const studentRecord: [string, number] = ["광수", 1]; //tuple
const num: number[][] = [[1,2],[3]];
const num2: Array<Array<number>> = [[1,2],[3]];
//뭔가 c# 같음. List<int> scores = new List<int>();
// 물론 [] 꼴을 권장
//4
if (true)
{
var itsvar = '';
let itslet = '';
}
itsvar; //오류 안남. 즉, scope를 탈출
// itslet; //오류남
export {};
#4. 객체와 함수에 타입
/*
* 제목 : 객체에 커스텀 타입 붙이기
*
* < 요약 >
* type 으로 정의 가능
*
* [2026/09/17 00:43:03 / 1_typedef.ts]
*/
const student: {name:string, age:number} = {name:"ㅇㅇ", age:0};
type studentType = {name:string, age:number, gender?: boolean}; //python의 class 느낌
type studentType2 = {name:string; age:number, gender?: boolean}; //comma 대신 semicolon 써도 ㄱㅊ
const gildong: studentType = {
name : "길동",
age : 1,
} //instance 느낌
console.log(gildong);
//{ name: '길동', age: 1 }
//undefined로 설정되지 않고 아예 없다.
const gildong2: studentType = {
name : "길동",
age : 1,
gender: true,
}
console.log(gildong2);
//{ name: '길동', age: 1, gender: true }
/*
* 제목 : 함수에 type def
*
* < 요약 >
* python은 class에서 그쳤다면 js는 def의 입출력에 관해서도 class를 지원하는 듯
*
* [2026/09/17 12:34:37 / week1-typescript/4/2_functypedef]
*/
function printGreeting(studentName: string) {
console.log("반가워요, " + studentName + " 님!");
}
function printGreeting2(studentName: string): void {
console.log("반가워요, " + studentName + " 님!");
}
const add = (a: number, b: number) => {
return a + b;
};
const add2 = (a: number, b: number): number => {
return a + b;
};
const add3 = (a: number, b: number): number => a + b;
type addition = (a: number, b: number) => number;
//숫자, 숫자 입력이고 숫자 리턴할거임
const add4: addition = (c, d) => c + d;
//숫자, 숫자 입력받고 숫자+숫자=(숫자) 리턴
/*
* 제목 : type override 살펴보기
*
* < 요약 >
* 같은 타입이면 never 오류 안남. 다른 타입이면 오류남.
* 즉, 타입&이름을 검사. 따라서 내용 override는 주의해야 할 듯
*
* [2026/09/17 12:43:00 / week1-typescript/4/3_type]
*/
type MemberProfile = {
name: string;
};
type GithubProfile = {
githubId: string;
};
type MemberWithGithub = MemberProfile & GithubProfile;
const gwangsooProfile: MemberWithGithub = {
name: "광수",
githubId: "gwangsoo",
};
console.log(gwangsooProfile.name, gwangsooProfile.githubId);
//override test
type a = {age:number, name:number};
type b = {name:string};
type c = a & b;
// let tmp:c = {age:1, name:12};
// 'number' 형식은 'never' 형식에 할당할 수 없습니다.ts(2322)
type tmp = number & string;
// any로 우회하여 "임의의 값"을 주입
const dummy = "test" as any as tmp;
//test 를 any로 변환
//any를 tmp(never)로 변환. 이를 허용해줌
// 자바스크립트 실행 시점의 타입을 출력 (결과는 "string")
console.log(typeof dummy);
type IsEqual<T, U> =
(<G>() => G extends T ? 1 : 2) extends
(<G>() => G extends U ? 1 : 2)
? true
: false;
/*T extends U (T가 U에 포함되는가?)라고 물어보면,
타입스크립트가 자기 마음대로 유니온 타입(A | B) 같은
복잡한 걸 쑥쑥 쪼개면서 "어? 비슷하네? 참(true)!"
하고 대충 넘어가는 버그가 생깁니다.
1. G라는 빈 상자(제네릭)를 만듭니다.
2. 그 상자에다가 "네가 가진 타입 T와 똑같이 반응하는지 테스트해 볼게"라고 시킵니다.
3. 그리고 그 테스트 결과를 함수 타입으로 감싸버립니다.
이렇게 함수 타입 안으로 T와 U를 숨겨버리면,
타입스크립트는 유니온 타입 등을 제멋대로 쪼개지 못하고
오직 두 타입의 구조가 완벽하게 일치할 때만 같다고 인정하게 됩니다.
*/
type tmp1 = {
a: string;
}
type tmp2 = {
a: string;
}
type tmp1andtmp2 = tmp1 & tmp2;
type tmp3 = {
a: string;
b: number; // 내용이 다른 확장된 인터페이스
}
//내용 같음
type Result1 = IsEqual<tmp1, tmp1andtmp2>;
// false
// Case 2: 내용이 다른 경우 (tmp1과 tmp3)
type Result2 = IsEqual<tmp1, tmp3>;
// false
/*
* 제목 : interface 테스트
*
* < 요약 >
*
*
* [2026/09/17 12:54:20 / week1-typescript/4/4_interface]
*/
type StudentName = string;
interface StudyMember {
name: StudentName;
}
interface StudyMember {
level: number;
} //override 및
const member: StudyMember = {
name: "광수",
level: 1,
};
interface Parent { a: string; }
interface Child extends Parent { b: number; } // Parent와 Child는 별개의 존재
interface Child2 extends Parent { a: string; }
// interface Child2 extends Parent { a: number; }
// 후속 속성 선언에 같은 형식이 있어야 합니다.
// 'a' 속성이 'string' 형식이어야 하는데 여기에는 'number' 형식이 있습니다.ts(2717)
interface asdf { a: string; }
// 여기서 새로운 걸 만드는 게 아니라, 원래 있던 asdf 자체가 커짐
interface asdf { b: number; }
//오류 테스트
interface tmp {a: string};
const b:tmp = {a : 'ㅇㅇ'};
console.log(b);
interface tmp {a: string};
// 그냥 불필요한 코드가 되어버림.
console.log(b);
interface tmp2 {a: string};
// interface tmp2 {a: number};
// 후속 속성 선언에 같은 형식이 있어야 합니다.
// 'a' 속성이 'string' 형식이어야 하는데 여기에는 'number' 형식이 있습니다.ts(2717)
//type은 &(override)에서 오류 안남. 값 대입할 때만 오류남
//interface는 override에서 오류 남. << 이게 장점
// 1. 두 타입이 같은지 판별하는 유틸리티 타입 (Conditional Type 활용)
type IsEqual<T, U> =
(<G>() => G extends T ? 1 : 2) extends
(<G>() => G extends U ? 1 : 2)
? true
: false;
/*T extends U (T가 U에 포함되는가?)라고 물어보면,
타입스크립트가 자기 마음대로 유니온 타입(A | B) 같은
복잡한 걸 쑥쑥 쪼개면서 "어? 비슷하네? 참(true)!"
하고 대충 넘어가는 버그가 생깁니다.
1. G라는 빈 상자(제네릭)를 만듭니다.
2. 그 상자에다가 "네가 가진 타입 T와 똑같이 반응하는지 테스트해 볼게"라고 시킵니다.
3. 그리고 그 테스트 결과를 함수 타입으로 감싸버립니다.
이렇게 함수 타입 안으로 T와 U를 숨겨버리면,
타입스크립트는 유니온 타입 등을 제멋대로 쪼개지 못하고
오직 두 타입의 구조가 완벽하게 일치할 때만 같다고 인정하게 됩니다.
*/
// --- 테스트용 인터페이스 ---
interface tmp1 {
a: string;
}
interface tmp2 {
a: string; // tmp1과 완전히 같은 내용
}
interface tmp3 {
a: string;
b: number; // 내용이 다른 확장된 인터페이스
}
// --- 2. 비교 실행 및 결과 확인 ---
// Case 1: 완전히 같은 타입인 경우 (tmp1과 tmp2)
type Result1 = IsEqual<tmp1, tmp2>;
// true (마우스 올려보면 true로 나옴)
// Case 2: 내용이 다른 경우 (tmp1과 tmp3)
type Result2 = IsEqual<tmp1, tmp3>;
// false (내용이 다르므로 false)
/*
* 제목 : 미니실습 오류고치기
*
* < 요약 >
* ...가 python의 unpacking인 *나 **랑 똑같다.
* 즉, 위에 기본값 쓰고 밑에서 유저 인풋 받으면
* 자연스레 오버라이드 되면서 기본값 설정 ㄱㄴ
*
* [2026/09/17 13:44:07 / week1-typescript/4/5_mini_mission]
*/
/*before
type StudyMember = {
name: string;
level: number;
isLeader: boolean;
};
const member: StudyMember = {
name: "광수",
level: "1",
};
function createMemberCard(studyMember: StudyMember) {
return studyMember.name + " 님, " + studyMember.level + "레벨";
}
console.log(createMemberCard(member));
*/
type StudyMember = {
name: string;
level: number;
isLeader: boolean;
};
const member: StudyMember = {
name: "광수",
level: 1,
isLeader: false,
};
function createMemberCard(studyMember: StudyMember) {
return studyMember.name + " 님, " + studyMember.level + "레벨";
}
console.log(createMemberCard(member));
//is Leader 기본값 설정하기
type settings = {
name: string;
level: number;
isLeader?: boolean;
theme?: "dark" | "light";
};
const input: settings = {
name: "길동",
level: 1,
theme: "dark"
}; //유저가 쓴 것. isLeader는 없다
const final: settings = {
isLeader: false, //기본값
theme: "light", //기본값
...input
}
console.log(input);
//{ name: '길동', level: 1, theme: 'dark' }
console.log(final);
//{ isLeader: false, theme: 'dark', name: '길동', level: 1 }
//... 은 python의 unpacking (*나 **) 문법이랑 걍 똑같음
#5. union type과 type 좁히기
/*
* 제목 : union type
*
* < 요약 >
* ts 컴파일러 생각보다 더 똑똑함
* 오류를 사전에 정말 잘 막아준다.
*
* [2026/09/17 13:54:55 / week1-typescript/5/1_uniontype]
*/
function printMemberId(memberId: string | number) {
console.log(memberId);
}
printMemberId("member-01");
printMemberId(1);
function formatMemberId(memberId: string | number) {
if (typeof memberId === "number" || typeof memberId === "string")
{
memberId //(parameter) memberId: string | number
}
if (typeof memberId === "string") {
return memberId.toUpperCase();
}
if(typeof memberId === "function")
{
memberId
//(parameter) memberId: never
}
if (typeof memberId === "number" || typeof memberId === "string")
{
memberId
// 여기서 memberId가 number로만 나오는 이유
//위에서 memberId가 string이면 return해서 나가기 때문에.
if (typeof memberId === "string") {
memberId
//그러니 number인데 string => never 됨
}
}
return "MEMBER-" + memberId;
}
type MemberRole = "leader" | "member";
type AttendanceStatus = "present" | "late" | "absent";
const gwangsooRole: MemberRole = "leader";
const todayStatus: AttendanceStatus = "present";
const tmp: MemberRole = "leader";
// const tmp2: MemberRole = "asdfasf";
// '"asdfasf"' 형식은 'MemberRole' 형식에 할당할 수 없습니다.ts(2322)
//오타 막아줘서 아주 중요한 듯
/*
* 제목 : 미니실습
*
* < 요약 >
*
*
* [2026/09/17 14:03:39 / week1-typescript/5/2_mini_mission]
*/
type MemberRole = "leader" | "member";
function getRoleText(role: MemberRole): string
{
if(role === "leader") return "스터디를 이끌어요."
return '스터디에 참여해요.'
}
getRoleText("leader");
getRoleText("member");
// getRoleText("hi");
// '"hi"' 형식의 인수는 'MemberRole' 형식의 매개 변수에 할당될 수 없습니다.ts(2345)
#6 null & undefined
/*
* 제목 : null과 undefined
*
* < 요약 >
*
*
* [2026/09/17 14:17:52 / week1-typescript/6/1_null_undefined]
*/
type StudyMember = {
name: string;
githubId?: string;
};
const members: StudyMember[] = [
{ name: "광수", githubId: "gwangsoo" },
{ name: "지수" },
];
let selectedMember: StudyMember | null = null;
const foundMember = members.find((member) => member.name === "현우");
//1개만 가져옴
//found_member = next((m for m in members if m.name == "현우"), None)
//next(generator, 기본)
//과 동일
console.log(selectedMember); // null
console.log(foundMember); // undefined
console.log(Boolean(false)); // false
console.log(Boolean(0)); // false
console.log(Boolean("")); // false
console.log(Boolean("false")); // true
console.log(Boolean([])); // true
console.log(Boolean({})); // true
//이런 비직관적인 내용 때문에 직접 비교가 안전
// foundMember가 undefined.
// githubId가 undefined로 반환
const githubId = foundMember?.githubId;
// const githubId2 = foundMember.githubId;
// 'foundMember'은(는) 'undefined'일 수 있습니다.ts(18048)
const studyHour: number | undefined = 0;
console.log(studyHour || 1); // 1
//studyHour가 falsy => 1씀
console.log(studyHour ?? 1); // 0
//studyHour가 null | undefined => 1씀
//즉, 모든 falsy 대체하려면 ||
const nickname: string | null = "";
console.log(nickname || "닉네임 없음"); // "닉네임 없음"
console.log(nickname ?? "닉네임 없음"); // ""
const displayGithubId = foundMember?.githubId ?? "등록되지 않음";
//undefined ?? "등록되지 않음"; => "등록되지 않음"
console.log(displayGithubId);
// ! <- 반드시 값이 있다. non-null
// const tmp = foundMember!.name;
// console.log(tmp);
// 그러나 undefined 였으니 컴파일에서 오류남
/*
* 제목 : 미니미션
*
* < 요약 >
*
*
* [2026/09/17 14:27:53 / week1-typescript/6/2_mini_mission]
*/
type StudyMember = {
name: string;
githubId?: string;
};
const members: StudyMember[] = [
{ name: "광수", githubId: "gwangsoo" },
{ name: "지수" },
];
const selectedMember: StudyMember | null = null;
const foundMember = members.find((member) => member.name === "현우");
if(foundMember !== undefined)
{
console.log(foundMember);
}
const studyHour: number = 0;
console.log(studyHour || 123); //123
console.log(studyHour ?? 123); //0
const targetMember: StudyMember = members[1];
console.log(targetMember?.githubId ?? "등록되지 않음");
#7 any unknown
/*
* 제목 : any랑 unknown
*
* < 요약 >
* unknown은 검사해야 함.
*
* [2026/09/18 01:02:25 / week1-typescript/7/1_unknown]
*/
function tmp(name: any)
{
return name.toUpperCase();
// string 아니면 오류 가능
}
function tmp2(name: unknown)
{
if(typeof name === "string")
{
return name.toUpperCase();
}
}
// tmp(1) 오류
tmp2("a")
function isActuallyString(val: unknown): val is string {
// 런타임에는 사실 string이 아니거나 조작된 값을 반환하더라도
// 타입 시스템 입장에서는 string이라고 믿게 만듦
return true;
}
//:변수 is 타입
//이 함수가 true 리턴하면, 변수는 타입
/*
function 함수이름(매개변수: 타입): [매개변수이름] is [바뀌길 원하는 타입] {
return 참/거짓;
}
*/
function tmp3(a: unknown) {
if (isActuallyString(a)) {
// 컴파일러는 여기서 a가 string이라고 믿지만, 실제 값은 아닐 수 있음
a.toUpperCase();
}
}
// tmp3(12) 오류
/*
* 제목 : 미니미션
*
* < 요약 >
*
*
* [2026/09/18 01:12:38 / week1-typescript/7/2_mini_mission]
*/
function formatStudyWeek(val : unknown)
{
if(typeof val === "number")
{
return `현재 ${val}주차에요.`;
}
if(typeof val === "string")
{
return `입력한 주차: ${val}`;
}
return "주차를 확인할 수 없어요."
}
console.log(formatStudyWeek(1));
console.log(formatStudyWeek("1"));
console.log(formatStudyWeek(true));
console.log(typeof formatStudyWeek(true)); //string
#8 generic
/*
* 제목 : generic
*
* < 요약 >
* 객체 만들 때 {value} 면 {value : value의값} 으로 됨
* type이 오른쪽으로 흐름
*
* [2026/09/18 01:15:44 / week1-typescript/8/1_generic]
*/
function keepVal<theType>(value: theType): theType
{
return value;
}
console.log(typeof keepVal<string>("ㅎㅇ")); //string
function tmp<T>(value: T)
{
return { value };
}
function tmp2<T>(value: T): {value: T}
{
return { value: value };
// tmp 함수랑 같음
}
console.log(tmp<string>("ㅎㅇ").value);
console.log(tmp2<number>(123).value);
function createBox(value: any) {
return { value };
}
const box = createBox(100).value;
// (property) value: any
// ts가 에러를 잡아주지 못함! (런타임에 터짐)
type NamedMember = {
name: string;
};
function getMemberName<T extends NamedMember>(member: T) {
return member.name;
}
//getMemberName({age:1});
//'{ age: number; }' 형식의 인수는
//'NamedMember' 형식의 매개 변수에 할당될 수 없습니다.
//최소 조건인 name:string이 없음.
console.log(getMemberName({age:1} as any));
//빨간 줄 안 뜸
//undefined
console.log(getMemberName<any>({age:1}));
//undefined
console.log(getMemberName({name:"ㅎㅇ", age:1}));
/*
* 제목 : 미니 실습
*
* < 요약 >
*
*
* [2026/09/18 13:01:36 / week1-typescript/8/2_mini_mission]
*/
type member = {
name: string
}
function createBox<T>(value: T)
{
return {value};
}
createBox("12");
createBox(12);
const tmp: member = {name : "ㅎㅇ"};
createBox(tmp);
#9. strict
/*
* 제목 : 미니 실습 오류 찾기
*
* < 요약 >
*
*
* [2026/09/18 13:03:40 / week1-typescript/9/1_mini_mission]
*/
/*before
type WeeklyGoal = {
title: string;
targetCount: number;
};
const weeklyGoal: WeeklyGoal = {
title: "TypeScript 예제 연습",
targetCount: "3", <- 여기 틀림
};
function printGoal(goal: WeeklyGoal): string {
console.log(goal.title); <-리턴이 없음
}
*/
type WeeklyGoal = {
title: string;
targetCount: number;
};
const weeklyGoal: WeeklyGoal = {
title: "TypeScript 예제 연습",
targetCount: 3
};
function printGoal(goal: WeeklyGoal): string {
console.log(goal.title);
return goal.title;
}
//반환 타입 명시한 이유
//보통 프린트 잘 됐는지 체크하려고 씀
//근데 그러면 boolean 리턴이 낫지 않을까?
#선택미션
/*
* 제목 : 선택미션
*
* < 요약 >
*
*
* [2026/09/18 13:36:30 / week1-typescript/optional_mission]
*/
function formatMemberId(input: unknown): string
{
if(typeof input === "number")
{
return `ID번호 : ${input}`
}
if(typeof input === "string")
{
return `ID텍스트 : ${input}`
}
return `ID?? : ${input}`
}
#필수미션
/*
* 제목 : 필수 미션
*
* < 요약 >
*
*
* [2026/09/18 13:39:20 / week1-typescript/main_mission]
*/
//회원의 ID, 이름, 역할과 선택 값인 GitHub 아이디를 타입으로 표현하고, 서로 다른 정보를 가진 회원 두 명 이상을 작성해요.
type typeMember = {
ID : number,
name : string,
githubID? : string,
};
const dataMember: typeMember[] = [
{ID:1, name:"ㅇㅇ"},
{ID:2, name:"ㄴㄴ", githubID:"nono"},
]
//회원 ID로 정보를 찾아 안내 문구를 만들고, GitHub 아이디가 없는 회원과 존재하지 않는 회원도 오류 없이 처리해요.
function getMemeberByID(targetID: number): typeMember | undefined
{
return dataMember.find((member) => member.ID === targetID);
}
function getInfoTextByMember(targetMember: typeMember | undefined): string
{
if(typeof targetMember === "undefined")
{
return `회원이 존재하지 않습니다.`
}
return `ID : ${targetMember.ID}
Name : ${targetMember.name}
GithubID : ${targetMember.githubID ?? "없음"}
`
}
//회원 ID 1, 2, 999를 전달한 결과를 확인하고 pnpm exec tsc --noEmit, 컴파일과 실행을 모두 완료해요.
const IDsToCheck: number[] = [1, 2, 999];
IDsToCheck.forEach(targetID => {
console.log(`ID : ${targetID}인 회원을 확인 중..`);
const targetMember = getMemeberByID(targetID);
const infoText = getInfoTextByMember(targetMember);
console.log(infoText);
});
/*
ID : 1인 회원을 확인 중..
ID : 1
Name : ㅇㅇ
GithubID : 없음
ID : 2인 회원을 확인 중..
ID : 2
Name : ㄴㄴ
GithubID : nono
ID : 999인 회원을 확인 중..
회원이 존재하지 않습니다.
*/
type과 interface는 표현 범위와 확장 방식에서 어떤 차이가 있을까요? type은 &로 합치면 never 되고 오류가 안남 interface는 오류나서 바로 고치기 ㄱㄴtypeof와 판별 프로퍼티는 타입을 어떻게 좁히나요? 그 scope 안에 어떤 타입 들어가는 지 자동으로 잡아줌 판별 union으로 특정 상황에서만 나오는 key를 나눠서 설정 ㄱㄴnull과 undefined가 포함된 값을 안전하게 다룰 때 옵셔널 체이닝과 널 병합 연산자는 어떤 역할을 하나요? ?. ⇒ 없으면 undefined로 해줌 ??나 ||로 없으면 값 어떻게 채울 지 명시 가능. ??가 null이나 undefined일 때만 처리하므로, ?? 추천. ||는 falsyany와 unknown은 타입 검사를 허용하는 방식이 어떻게 다른가요? any는 타입 검사를 끔 unknown은 밑에 typeof로 내부 scope에서 타입 조건 가능unknown과 제네릭은 각각 어떤 상황에 알맞을까요? unknown은 받고 typeof 검사 ⇒ 외부에서 데이터 가져올 때 generic은 타입 기억. 즉, 들어올 때부터 검사 ⇒ 근데 꼭 입력에 그 Type을 안 받아도 됨. function arg에 타입을 받을 수가 없어서 Generic으로 type 받기. function tmp(): t 로 tmp ⇒ return을 string으로 받기 가능