Skip to content

Commit 740eb30

Browse files
committed
[2주차] chp5 ~ 7, 10 + 예제
1 parent 2db1500 commit 740eb30

File tree

7 files changed

+381
-0
lines changed

7 files changed

+381
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export type Cipher = (text: string) => string;
2+
3+
export function createCipher(cipher: Cipher) {
4+
return (text: string) => {
5+
let result = "";
6+
for (const alp of text) {
7+
result += cipher(alp);
8+
}
9+
return result;
10+
}
11+
}

백윤서/chapter05/02-dr-on.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export type ParamsType = (text: string) => string;
2+
3+
export function createAdvancedCipher(onVowel: ParamsType, onConsonant: ParamsType, onPunctuation: ParamsType) {
4+
return (text: string) => {
5+
let result = "";
6+
for (const alp of text) {
7+
const reg1 = /[aeiou]/i;
8+
const reg2 = /[bcdfghjklmnpqrstvwxyz]/i;
9+
if (reg1.test(alp)) result += onVowel(alp);
10+
else if (reg2.test(alp)) result += onConsonant(alp);
11+
else result += onPunctuation(alp);
12+
}
13+
return result;
14+
}
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export interface CodeCracker {
2+
attempts: number;
3+
makeGuess: (text: string, attempt: number) => string;
4+
validateGuess: (guess: string) => boolean;
5+
}
6+
7+
export function createCodeCracker(obj: CodeCracker) {
8+
const { attempts, makeGuess, validateGuess } = obj;
9+
return (text: string) => {
10+
for (let i = 0; i < attempts; i += 1) {
11+
const guessStr = makeGuess(text, i);
12+
if (validateGuess(guessStr)) return guessStr;
13+
}
14+
return undefined;
15+
}
16+
}

백윤서/chapter05/README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# 5장 함수
2+
3+
## 5.1 함수 매개변수
4+
5+
### 선택적 매개변수
6+
7+
함수의 선택적 매개변수는 항상 암묵적으로 `undefined`가 될 수 있다. 선택적 매개변수는 `| undefined`를 포함하는 유니언 타입 매개변수와는 다르다. 선택적 매개변수가 아닌 매개변수는 값이 명시적으로 `undefined`이어도 명시적으로 항상 제공되어야 한다.
8+
9+
또한 함수에서 사용되는 모든 선택적 매개변수는 마지막 매개변수여야 한다. 필수 매개변수 전에 선택적 매개변수를 위치시키면 타입스크립트 구문 오류가 발생한다.
10+
11+
## 5.2 반환 타입
12+
13+
### 명시적 반환 타입
14+
15+
함수 반환 타입을 명시적으로 선언하지 않는 것이 좋지만 함수에서 반환 타입을 명시적으로 선언하는 방식이 유용할 때가 있다.
16+
17+
- 가능한 반환값이 많은 함수가 항상 통일한 타입의 값을 반환하도록 강제
18+
- 타입스크립트는 재귀 함수의 반환 타입을 통해 타입을 유추하는 것을 거부
19+
- 매우 큰 프로젝트에서 타입스크립트 타입 검사 속도를 높일 수 있음
20+
21+
## 5.4 그 외 반환 타입
22+
23+
### `never` 반환 타입
24+
25+
`never` 반환 함수는 의도적으로 항상 오류를 발생시키거나 무한루프를 실행하는 함수이다. 함수가 절대 반환하지 않도록 의도하려면 명시적 `never` 타입 애너테이션을 추가해 해당 함수를 호출한 후 모든 코드가 실행되지 않음을 나타내야 한다.
26+
27+
```ts
28+
function fail(msg: string): never {
29+
throw new Error(`failure: ${msg}`);
30+
}
31+
32+
function workWithUnsafeParam(param: unknown) {
33+
if (typeof param !== 'string') fail('param should be a string.');
34+
35+
param.toUpperCase();
36+
}
37+
```
38+
39+
## 5.5 함수 오버로드
40+
41+
하나의 최종 구현 시그니처와 그 함수의 본문 앞에 서로 다른 버전의 함수 이름, 매개변수, 변환 타입을 여러 번 선언하여 선택적 매개변수와 나머지 매개변수만으로 표현할 수 없는 다른 매개변수로 호출할 수 있다. 이 함수를 오버로드 시그니처라고 불린다.
42+
43+
오버로드된 함수 호출에 대해 구문 오류를 생성할지 여부를 결정할 때 타입스크립트는 함수의 오버로드 시그니터만 확인한다.
44+
45+
```ts
46+
function createDate(timestamp: number): Date;
47+
function createDate(month: number, day: number, year: number): Date;
48+
function createDate (monthOrTimestamp: number, day?: number, year?: number) {
49+
return day === undefined || year === undefined
50+
? new Date (monthOrTimestamp)
51+
: new Date (year, monthOrTimestamp, day);
52+
}
53+
54+
createDate(8347289745);
55+
createDate(7, 27, 1987);
56+
57+
createDate(4, 1); // 2개의 인수를 허용하는 오버로드 시그니처가 없으므로 타입 오류 발생
58+
```
59+
60+
### 호출 시그니처 호환성
61+
62+
오버로드도니 함수의 구현에서 사용되는 구현 시그니처는 매개변수 타입과 반환 타입에 사용하는 것과 동일하다. 따라서 함수의 오버로드 시그니처에 있는 반환 타입과 각 매개변수는 구현 시그니처에 있는 동일한 인덱스의 매개변수에 할당할 수 있어야 한다. 즉, 구현 시그니처는 모든 오버로드 시그니처와 호환돼야 한다.
63+
64+
```ts
65+
function format(data: string): string;
66+
function format(data: string, needle: string): string;
67+
68+
function format(getData: () => string): string;
69+
70+
// Error: This overload signature is not compatible with tits implementation signature
71+
```

백윤서/chapter06/README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 6장 배열
2+
3+
## 6.2 배열 멤버
4+
5+
### 주의 사항: 불안정한 멤버
6+
7+
타입스크립트는 모든 배열의 멤버에 대한 접근이 해당 배열의 멤버를 반환한다고 가정하지만, 자바스크립트에서조차도 배열의 길이보다 큰 인덱스로 배열 요소에 접근하면 `undefined`를 제공한다.
8+
9+
```ts
10+
const arr: string[] = ['a'];
11+
12+
arr[99999]; // 타입 오류 없음
13+
```
14+
15+
타입스크립트는 검색된 배열의 멤버가 존재하는지 의도적으로 확인하지 않는다.
16+
17+
## 6.3 스프레드와 나머지 매개변수
18+
19+
### 스프레드
20+
21+
서로 다른 타입의 두 배열을 함께 스프레드해 새 배열을 생성하면 새 배열은 두 개의 원래 타입 중 어느 하나의 요소인 유니언 타입 배열로 이해된다.
22+
23+
### 나머지 매개변수 스프레드
24+
25+
나머지 매개변수를 위한 인수로 사용되는 배열은 나머지 매개변수와 동일한 배열 타입을 가져야 한다.
26+
27+
## 6.4 튜플
28+
29+
### 튜플 할당 가능성
30+
31+
가변 길이의 배열 타입은 튜플 타입에 할당할 수 없다.
32+
33+
타입스크립트는 튜플 타입의 튜플에 얼마나 많은 멤버가 있는지 알고 있기 때문에 길이가 다른 튜플은 서로 할당할 수 없다.
34+
35+
튜플로 나머지 매개변수의 타입을 명시한다면 타입의 잘못된 순서로 인한 내용의 불일치 가능성을 줄이고 타입의 안전을 보장할 수 있다.
36+
37+
### 튜플 추론
38+
39+
타입스크립트에서는 값이 일반적인 배열 타입 대신 좀 더 구체적인 튜플 타입이어야 함을 두 가지 방법으로 나타낼 수 있다.
40+
41+
- 명시적 튜플 타입
42+
43+
```ts
44+
// 반환 타입: [string, number]
45+
function firstCharAndSizeExplicit(input: string): [string, number] {
46+
return [input[0], input.length];
47+
}
48+
49+
// firstChar 타입: string
50+
// size 타입: number
51+
const [firstChar, size] = firstCharAndSizeExplicit('Cathay Williams');
52+
```
53+
54+
- `const` 어서션(assertion)
55+
56+
타입스크립트는 코드 변경에 따라 작성 및 수정이 필요한 구문을 추가해야 하는데 이 대안으로 값 뒤에 넣을 수 있는 `const` 어서션인 `as const` 연산자를 제공한다. `const` 어서션은 타입스크립트에 타입을 유추할 때 읽기 전용이 가능한 값 형식을 사용하도록 지시한다.
57+
58+
```ts
59+
// 타입: (string | number)[]
60+
const unionArray = [1157, 'Tomoe'];
61+
62+
// 타입: readonly [1157, 'Tomoe]
63+
const readonlyTuple = [1157, 'Tomoe'] as const; // 배열이 튜플로 처리되어야 함을 나타냄
64+
```
65+
66+
`const` 어서션은 유연한 크기의 배열을 고정된 크기의 튜플로 전환하는 것 뿐만 아니라 해당 튜플이 읽기 전용이고 값 수정이 예상되는 곳에서 사용할 수 없음을 나타낸다.(할당 불가능)
67+
68+
읽기 전용 튜플은 함수 반환에 편리하다.
69+
70+
```ts
71+
function firstCharAndSizeAsConst(input: string) {
72+
return [input[0], input.length] as const;
73+
}
74+
75+
// firstChar 타입: string
76+
// size 타입: number
77+
const [firstChar, size] = firstCharAndSizeAsConst('Ching Shih');
78+
```

백윤서/chapter07/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# 7장 인터페이스
2+
3+
## 7.1 타입 별칭 vs 인터페이스
4+
5+
- 인터페이스는 속성 증가를 위해 병합할 수 있다.
6+
7+
- 인터페이스는 클래스가 선언된 구조의 타입을 확인하는 데 사용할 수 있지만, 타입별칭은 사용할 수 없다.
8+
9+
- 일반적으로 인터페이스에서 타입 스크립트 타입 검사기가 더 빨리 작동한다. 인터페이스는 타입 별칭이 하는 것처럼 새로운 객체 리터럴의 동적인 복사 붙여넣기보다 내부적으로 더 쉽게 캐시할 수 있는 명명된 타입을 선언한다.
10+
11+
- 인터페이스는 이름 없는 객체 리터럴의 별칭이 아닌 이름 있는 (명명된) 객체로 간주되므로 어려운 특이 케이스에서 나타나는 오류 메세지를 좀 더 쉽게 읽을 수 있다.
12+
13+
## 7.2 속성 타입
14+
15+
### 숫자 인덱스 시그니처
16+
17+
자바스크립트가 암묵적으로 객체 속성 조회 키를 문자열로 변환하지만 객체의 키로 숫자만 허용하는 경우가 필요하다. 타입스크립트 인덱스 시그니처는 키로 string 대신 number 타입을 사용할 수 있지만, 명명된 속성은 그 타입을 포괄적인 용도의 string 인덱스 시그니처의 타입으로 할당할 수 있어야 한다.
18+
19+
```ts
20+
interface MoreNarrowNumbers {
21+
[i: number]: string;
22+
[i: string]: string | undefined;
23+
}
24+
25+
const mixesNumbersAndStrings: MoreNarrowNumbers = {
26+
0: '',
27+
key1: '',
28+
key2: undefined,
29+
};
30+
31+
interface MoreNarrowStrings {
32+
[i: number]: string | undefined;
33+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34+
// Error: number 인덱스 유형 string | undefined 를 string 인덱스 유형 string에 할당할 수 없습니다.
35+
[i: string]: string;
36+
}
37+
```
38+
39+
`MoreNarrowNumbers` 인터페이스는 `string``string | undefined` 에 할당할 수 있지만, `MoreNarrowStrings` 인터페이스는 `string | undefined``string`에 할당할 수 없다.
40+
41+
## 7.4 인터페이스 병합
42+
43+
### 이름이 충돌되는 멤버
44+
45+
병합된 인터페이스는 타입이 다른 동일한 이름의 속성을 여러 번 선언할 수 없다. 속성이 이미 인터페이스에 선언되어 있다면 나중에 병합된 인터페이스에서도 동일한 타입을 사용해야한다.
46+
47+
```ts
48+
interface MergedProperties {
49+
same: (input: boolean) => string;
50+
different: (input: string) => string;
51+
}
52+
53+
interface MergedProperties {
54+
same: (input: boolean) => string;
55+
different: (input: number) => string;
56+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
57+
// Error: 후속 속성 선언에 같은 형식이 있어야 합니다.
58+
// different 속성이 (input: string) => string 형식이어야 하는데 여기에는 (input: number) => string 형식이 있습니다.
59+
}
60+
```
61+
62+
`MergedProperties` 인터페이스 선언에서는 `same` 속성이 모두 동일하기 때문에 문제가 없지만 `different` 속성은 타입이 서로 다르기 때문에 오류가 발생한다.
63+
64+
그러나 병합된 인터페이스는 동일한 이름과 다른 시그니처를 가진 메서드는 정의할 수 있다. 이렇게 하면 메서드에 대한 함수 오버로드가 발생한다.
65+
66+
```ts
67+
interface MergedMethods {
68+
different(input: string): string;
69+
}
70+
71+
interface MergedMethods {
72+
different(input: number): string;
73+
}
74+
```
75+
76+
`MergedMethods` 인터페이스는 두 가지 오버로드가 있는 `different` 메서드를 생성한다.

백윤서/chapter10/README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# 10장 제네릭
2+
3+
## 10.3 제네릭 클래스
4+
5+
```ts
6+
class Secret<Key, Value> {
7+
key: Key;
8+
value: Value;
9+
10+
constructor(key: Key, value: Value) {
11+
this.key = key;
12+
this.value = value;
13+
}
14+
15+
getValue(key: Key): Value | undefined {
16+
return this.key === key ? this.value : undefined;
17+
}
18+
}
19+
20+
const storage = new Secret(12345, 'luggage'); // 타입: Secret<number, string>
21+
storage.getValue(1987) // 타입: string | undefined
22+
```
23+
24+
`Secret` 클래스는 `Key`, `Value` 타입 매개변수를 선언한 다음 `Key`, `Value` 타입 매개변수를 멤버 속성, `constructor` 매개변수 타입, 메서드의 매개변수와 반환 타입으로 사용한다. 클래스를 타입 애너테이션으로 사용할 때는 해당 클래스의 제네릭 타입이 무엇인지를 타입스크립트에 나타내야 한다.
25+
26+
### 명시적 제네릭 클래스 타입
27+
28+
생성자에 전달된 인수에서 클래스 타입 인수를 유추할 수 없는 경우에는 타입 인수의 기본값은 `unknown`이 된다. 클래스 인스턴스는 다른 제네릭 함수 호출과 동일한 방식으로 명시적 타입 인수를 제공해서 기본값 `unknown`이 되는 것을 피할 수 있다.
29+
30+
### 정적 클래스 제네릭
31+
32+
클래스의 정적 멤버는 인스턴스 멤버와 구별되고 클래스의 특정 인스턴스와 연결되어 있지 않다. 클래스의 정적 멤버는 클래스 인스턴스에 접근할 수 없거나 타입 정보를 지정할 수 없다. 따라서 정적 클래스 메서드는 자체 타입 매개변수를 선언할 수 있지만 클래스에 선언된 어떤 타입 매개변수에도 접근할 수 없다.
33+
34+
## 10.5 제네릭 제한자
35+
36+
### 제네릭 기본값
37+
38+
타입 매개변수 뒤에 =와 기본 타입을 배치해 타입 인수를 명시적으로 제공할 수 있다. 기본값은 타입 인수가 명시적으로 선언되지 않고 유추할 수 없는 모든 후속 타입에 사용된다.
39+
40+
```ts
41+
interface Quote<T = string> {
42+
value: T;
43+
}
44+
45+
let explicit: Quote<number> = { value: 123 };
46+
47+
let implicit: Quote = { value: '123' };
48+
49+
let mismatch: Quote = { value: 123 };
50+
// Error: Type 'number' is not assignable to type 'string'
51+
```
52+
53+
모든 기본 타입 매개변수는 기본 함수 매개변수처럼 선언 목록의 맨 마지막에 와야 한다. 기본값이 없는 제네릭 타입은 기본값이 있는 제네릭 타입 뒤에 오면 안 된다.
54+
55+
## 10.6 제한된 제네릭 타입
56+
57+
타입스크립트는 타입 매개변수가 타입을 확장해야 한다고 선언할 수 있으며 별칭 타입에만 허용되는 작업이다. 타입 매개변수를 제한하는 구문은 매개변수 이름 뒤에 `extends` 키워드를 배치하고 그 뒤에 이를 제한할 타입을 배치한다.
58+
59+
`length: number`를 가진 모든 것을 설명하기 위해 `WithLength` 인터페이스를 생성하면 제네릭 함수가 `T` 제네릭에 대한 length를 가진 모든 타입을 받도록 구현할 수 있다.
60+
문자열, 배열 그리고 `length: number`를 가진 객체가 인자로 들어오는 것을 허용하지만 Date와 같은 형태에는 length 멤버가 없으므로 타입 오류가 발생한다.
61+
62+
```ts
63+
interface WithLength {
64+
length: number;
65+
}
66+
67+
function logWithLength<T extends WithLength>(input: T) {
68+
console.log(`Length: ${input.length}`);
69+
return input;
70+
}
71+
72+
logWithLength('123'); // 타입: string
73+
logWithLength([false, true]); // 타입: boolean[]
74+
logWithLength({ length: 123 }); // 타입: {length: number}
75+
76+
logWithLength(new Date());
77+
// Error: Argument of type 'Date' is not assignable to parameter of type 'WithLength'
78+
// Property 'length' is missing in type 'Date' but required in type 'WithLength'.
79+
```
80+
81+
## 10.7 Promise
82+
83+
### async 함수
84+
85+
자바스크립트에서 `async` 키워드를 사용해 선언한 모든 함수는 `Promise`를 반환한다.
86+
자바스크립트에서 `async` 함수에 따라서 반환된 값이 `Thenable`(`.then()` 메서드가 있는 객체, 실제로는 거의 항상 `Promise`)이 아닌 경우, `Promise.resolve`가 호출된 것처럼 `Promise`로 래핑된다.
87+
88+
89+
```ts
90+
// 타입: (text: string) => Promise<number>
91+
async function lengthAfterSecond(text: string) {
92+
await new Promise((resolve) => setTimeout(resolve, 1000));
93+
return text.length;
94+
}
95+
96+
// 타입: (text: string) => Promise<number>
97+
async function lengthImmediately(text: string) {
98+
return text.length;
99+
}
100+
```
101+
102+
`Promise`를 명시적으로 언급하지 않더라도 `async` 함수에서 수동으로 선언된 반환 타입은 항상 `Promise` 타입이 된다.
103+
104+
```ts
105+
// OK
106+
async function givesPromiseForString(): Promise<string> {
107+
return 'Done!';
108+
}
109+
110+
async function givesString(): string {
111+
// Error: The return type of an async function or method must be the global Promise<T> type.
112+
return 'Done!';
113+
}
114+
```

0 commit comments

Comments
 (0)