diff --git a/index.html b/index.html index 2c4f2b91..cee20be6 100644 --- a/index.html +++ b/index.html @@ -1062,7 +1062,7 @@
Consider a function in JavaScript called concat
that takes two array or tuple types and concatenates them together to make a new array.
배열이나 튜플 타입 두 개를 결합하여 새로운 배열을 만드는 JavaScript의 concat
함수에 대해서 생각해봅시다.
function concat(arr1, arr2) {
return [arr1, arr2];
}
-Also consider tail
, that takes an array or tuple, and returns all elements but the first.
그리고, 배열이나 튜플을 변수로 입력받아 첫 번째 원소를 제외한 나머지를 반환하는 tail
함수에 대해서도 생각해봅시다.
function tail(arg) {
const [_, result] = arg;
return result;
}
-How would we type either of these in TypeScript?
-For concat
, the only valid thing we could do in older versions of the language was to try and write some overloads.
TypeScript에서는 이 두 함수의 타입을 어떻게 정의할 수 있을까요?
+concat
의 경우, 이전 버전에서는 여러 개의 오버로드를 작성하는 방법이 유일했습니다.
function concat(arr1: [], arr2: []): [];
function concat<A>(arr1: [A], arr2: []): [A];
function concat<A, B>(arr1: [A, B], arr2: []): [A, B];
@@ -1084,8 +1084,8 @@ Variadic Tuple Types
function concat<A, B, C, D, E>(arr1: [A, B, C, D, E], arr2: []): [A, B, C, D, E];
function concat<A, B, C, D, E, F>(arr1: [A, B, C, D, E, F], arr2: []): [A, B, C, D, E, F];)
-Uh...okay, that's...seven overloads for when the second array is always empty.
-Let's add some for when arr2
has one argument.
음... 네, 이 오버로드들의 두 번째 배열은 전부 비어있습니다.
+이때, arr2
가 하나의 인자를 가지고 있는 경우를 추가해봅시다.
function concat<A2>(arr1: [], arr2: [A2]): [A2];
function concat<A1, A2>(arr1: [A1], arr2: [A2]): [A1, A2];
@@ -1095,19 +1095,19 @@ Variadic Tuple Types
function concat<A1, B1, C1, D1, E1, A2>(arr1: [A1, B1, C1, D1, E1], arr2: [A2]): [A1, B1, C1, D1, E1, A2];
function concat<A1, B1, C1, D1, E1, F1, A2>(arr1: [A1, B1, C1, D1, E1, F1], arr2: [A2]): [A1, B1, C1, D1, E1, F1, A2];
-We hope it's clear that this is getting unreasonable.
-Unfortunately, you'd also end up with the same sorts of issues typing a function like tail
.
This is another case of what we like to call "death by a thousand overloads", and it doesn't even solve the problem generally. -It only gives correct types for as many overloads as we care to write. -If we wanted to make a catch-all case, we'd need an overload like the following:
+이런 오버로딩 함수들은 분명 비합리적입니다.
+안타깝게도, tail
함수를 타이핑할 때도 이와 비슷한 문제에 직면하게 됩니다.
이것은 "천 개의 오버로드로 인한 죽음(death by a thousand overloads)"의 하나의 경우이며, 심지어 대부분 문제를 해결하지도 못합니다. +우리가 작성하고자 하는 만큼의 오버로드에 한해서만 올바른 타입을 제공합니다. +포괄적인 케이스를 만들고 싶다면, 다음과 같은 오버로드가 필요합니다.
function concat<T, U>(arr1: T[], arr2: U[]): Array<T | U>;
-But that signature doesn't encode anything about the lengths of the input, or the order of the elements, when using tuples.
-TypeScript 4.0 brings two fundamental changes, along with inference improvements, to make typing these possible.
-The first change is that spreads in tuple type syntax can now be generic. -This means that we can represent higher-order operations on tuples and arrays even when we don't know the actual types we're operating over. -When generic spreads are instantiated (or, replaced with a real type) in these tuple types, they can produce other sets of array and tuple types.
-For example, that means we can type function like tail
, without our "death by a thousand overloads" issue.
그러나 위 시그니처는 튜플을 사용할 때 입력 길이나 요소 순서에 대한 어떤 것도 처리하지 않습니다.
+TypeScript 4.0은 타입 추론 개선을 포함한 두 가지 핵심적인 변화를 도입해 이러한 타이핑을 가능하도록 만들었습니다.
+첫 번째 변화는 튜플 타입 구문의 스프레드 연산자에서 제네릭 타입을 사용할 수 있다는 점입니다. +우리가 작동하는 실제 타입을 모르더라도 튜플과 배열에 대한 고차함수를 표현할 수 있다는 뜻입니다. +이러한 튜플 타입에서 제네릭 스프레드 연산자가 인스턴스화(혹은, 실제 타입으로 대체)되면 또 다른 배열이나 튜플 타입 세트를 생산할 수 있습니다.
+예를 들어, tail
같은 함수를 "천 개의 오버로드로 인한 죽음(death by a thousand overloads)"이슈 없이 타이핑 할 수 있게 됩니다.
function tail<T extends any[]>(arr: readonly [any, T]) {
const [_ignored, rest] = arr;
return rest;
@@ -1117,45 +1117,45 @@ Variadic Tuple Types
const myArray = ["hello", "world"];
const r1 = tail(myTuple);
-// ^?
+// ^ = const r1: [2, 3, 4]
const r2 = tail([myTuple, myArray] as const);
-// ^?
+// ^ = const r2: [2, 3, 4, ...string[]]
-The second change is that rest elements can occur anywhere in a tuple - not just at the end!
+두 번째 변화는 나머지 요소가 끝뿐만 아니라 튜플의 어느 곳에서도 발생할 수 있다는 것입니다.
type Strings = [string, string];
type Numbers = [number, number];
type StrStrNumNumBool = [Strings, Numbers, boolean];
-// ^?
+// ^ = type StrStrNumNumBool = [string, string, number, number, boolean]
-Previously, TypeScript would issue an error like the following:
+이전에는, TypeScript는 다음과 같은 오류를 생성했었습니다:
A rest element must be last in a tuple type.
-
But with TypeScript 4.0, this restriction is relaxed.
-Note that in cases when we spread in a type without a known length, the resulting type becomes unbounded as well, and all the following elements factor into the resulting rest element type.
+TypeScript 4.0에서는 이러한 제한이 완화되었습니다.
+길이가 정해지지 않은 타입을 확장하려고할 때, 결과의 타입은 제한되지 않으며, 다음 모든 요소가 결과의 나머지 요소 타입에 포함되는 점에 유의하시기 바랍니다.
type Strings = [string, string];
type Numbers = number[];
type Unbounded = [Strings, Numbers, boolean];
-// ^?
+// ^ = type Unbounded = [string, string, ...(number | boolean)[]]
-By combining both of these behaviors together, we can write a single well-typed signature for concat
:
이 두 가지 동작을 함께 결합하여, concat
에 대해 타입이 제대로 정의된 시그니처를 작성할 수 있습니다.
type Arr = readonly any[];
function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [T, U] {
return [arr1, arr2];
}
-While that one signature is still a bit lengthy, it's just one signature that doesn't have to be repeated, and it gives predictable behavior on all arrays and tuples.
-This functionality on its own is great, but it shines in more sophisticated scenarios too.
-For example, consider a function to partially apply arguments called partialCall
.
-partialCall
takes a function - let's call it f
- along with the initial few arguments that f
expects.
-It then returns a new function that takes any other arguments that f
still needs, and calls f
when it receives them.
하나의 시그니처가 조금 길더라도, 반복할 필요가 없는 하나의 시그니처일 뿐이며, 모든 배열과 튜플에서 예측 가능한 행동을 제공합니다.
+이 기능은 그 자체만으로도 훌륭하지만, 조금 더 정교한 시나리오에서도 빛을 발합니다.
+예를 들어,함수의 매개변수를 부분적으로 적용하여 새로운 함수를 반환하는 partialCall
함수가 있다고 생각해봅시다.
+partialCall
은 다음과 같은 함수를 가집니다. - f
가 예상하는 몇 가지 인수와 함께 f
라고 지정하겠습니다.
+그 후, f
가 여전히 필요로 하는 다른 인수를 가지고, 그것을 받을 때 f
를 호출하는 새로운 함수를 반환합니다.
function partialCall(f, headArgs) {
return (tailArgs) => f(headArgs, tailArgs);
}
-TypeScript 4.0 improves the inference process for rest parameters and rest tuple elements so that we can type this and have it "just work".
+TypeScript 4.0은 나머지 파라미터들과 튜플 원소들에 대한 추론 프로세스를 개선하여 타입을 지정할 수 있고 "그냥 동작"하도록 할 수 있습니다.
type Arr = readonly unknown[];
function partialCall<T extends Arr, U extends Arr, R>(
@@ -1165,7 +1165,7 @@ Variadic Tuple Types
return (tailArgs: U) => f(headArgs, tailArgs);
}
-In this case, partialCall
understands which parameters it can and can't initially take, and returns functions that appropriately accept and reject anything left over.
이 경우, partialCall
은 처음에 취할 수 있는 파라미터와 할 수 없는 파라미터를 파악하고, 남은 것들은 적절히 수용하고 거부하는 함수들을 반환합니다.
// @errors: 2345 2554 2554 2345
type Arr = readonly unknown[];
@@ -1182,36 +1182,36 @@ Variadic Tuple Types
const f2 = partialCall(foo, "hello", 100, true, "oops");
-// This works!
+// 작동합니다!
const f3 = partialCall(foo, "hello");
-// ^?
+// ^ = const f3: (y: number, z: boolean) => void
-// What can we do with f3 now?
+// f3으로 뭘 할 수 있을까요?
-// Works!
+// 작동합니다!
f3(123, true);
f3();
f3(123, "hello");
-Variadic tuple types enable a lot of new exciting patterns, especially around function composition.
-We expect we may be able to leverage it to do a better job type-checking JavaScript's built-in bind
method.
-A handful of other inference improvements and patterns also went into this, and if you're interested in learning more, you can take a look at the pull request for variadic tuples.
Improving the experience around tuple types and parameter lists is important because it allows us to get strongly typed validation around common JavaScript idioms - really just slicing and dicing argument lists and passing them to other functions. -The idea that we can use tuple types for rest parameters is one place where this is crucial.
-For example, the following function that uses a tuple type as a rest parameter...
+가변 인자 튜플 타입은 특히 기능 구성과 관련하여 많은 새로운 흥미로운 패턴을 가능하게 합니다.
+우리는 JavaScript에 내장된 bind
메서드의 타입 체킹을 더 잘하기 위해 이를 활용할 수 있을 것이라고 기대합니다.
+몇 가지 다른 추론 개선 및 패턴들도 여기에 포함되어 있으며, 가변 인자 튜플에 대해 더 알아보고 싶다면, the pull request를 참고해보세요.
튜플 타입과 매개 변수 목록에 대해 개선하는 것은 일반적인 JavaScript 관용구에 대한 타입 유효성 검사를 강화시켜주기 때문에 중요합니다 - 실제로 인수 목록을 자르고 다른 함수로 전달만 해주면 됩니다. +나머지 매개 변수(rest parameter)에 튜플 타입을 사용할 수 있다는 생각은 아주 중요합니다.
+예를 들어, 튜플 타입을 나머지 매개 변수로 사용하는 다음 함수는...
function foo(args: [string, number]): void {
// ...
}
-...should appear no different from the following function...
+...다음 함수와 다르지 않아야 합니다...
function foo(arg0: string, arg1: number): void {
// ...
}
-...for any caller of foo
.
...foo
의 모든 호출자에 대해서도.
// @errors: 2554
function foo(arg0: string, arg1: number): void {
// ...
@@ -1222,37 +1222,37 @@ Labeled Tuple Elements
foo("hello", 42, true);
foo("hello");
-There is one place where the differences begin to become observable though: readability. -In the first example, we have no parameter names for the first and second elements. -While these have no impact on type-checking, the lack of labels on tuple positions can make them harder to use - harder to communicate our intent.
-That's why in TypeScript 4.0, tuples types can now provide labels.
+그러나 차이점이 보이기 시작한 부분은: 가독성입니다. +첫 번째 예시에서는, 첫 번째와 두 번째 요소에 대한 매개 변수 이름이 없습니다. +타입-검사에는 전혀 영향이 없지만, 튜플 위치에 라벨이 없는 것은 사용하기 어렵게 만듭니다 - 의도를 전달하기 어렵습니다.
+TypeScript 4.0에서 튜플 타입에 라벨을 제공하는 이유입니다.
type Range = [start: number, end: number];
-To deepen the connection between parameter lists and tuple types, the syntax for rest elements and optional elements mirrors the syntax for parameter lists.
+매개 변수 목록과 튜플 타입 사이의 연결을 강화하기 위해, 나머지 요소와 선택적 요소에 대한 구문이 매개 변수 목록의 구문을 반영합니다.
type Foo = [first: number, second?: string, rest: any[]];
-There are a few rules when using labeled tuples. -For one, when labeling a tuple element, all other elements in the tuple must also be labeled.
+라벨링 된 튜플을 사용할 때는 몇 가지 규칙이 있습니다. +하나는 튜플 요소를 라벨링 할 때, 튜플에 있는 다른 모든 요소들 역시 라벨링 되어야 합니다.
// @errors: 5084
type Bar = [first: string, number];
-It's worth noting - labels don't require us to name our variables differently when destructuring. -They're purely there for documentation and tooling.
+당연하게도 - 라벨은 구조 분해할 때 변수 이름을 다르게 지정할 필요가 없습니다. +이것은 순전히 문서화와 도구를 위해 필요합니다.
function foo(x: [first: string, second: number]) {
// ...
- // note: we didn't need to name these 'first' and 'second'
+ // 주의: 'first'와 'second'에 대해 이름 지을 필요 없음
const [a, b] = x;
a
-// ^?
+// ^ = const a: string
b
-// ^?
+// ^ = const b: number
}
-Overall, labeled tuples are handy when taking advantage of patterns around tuples and argument lists, along with implementing overloads in a type-safe way. -In fact, TypeScript's editor support will try to display them as overloads when possible.
-To learn more, check out the pull request for labeled tuple elements.
+전반적으로, 라벨링 된 튜플은 안전한 타입 방식으로 오버로드를 구현하는 것과 튜플과 인수 목록의 패턴을 활용할 때 편리합니다. +사실, TypeScript 에디터 지원은 가능한 경우 오버로드로 표시하려 합니다.
+더 알고 싶으시면, 라벨링된 튜플 요소에 대한 풀 리퀘스트를 확인해보세요
TypeScript 4.0 can now use control flow analysis to determine the types of properties in classes when noImplicitAny
is enabled.
TypeScript began its life as an attempt to bring traditional object-oriented types -to JavaScript so that the programmers at Microsoft could bring -traditional object-oriented programs to the web. As it has developed, TypeScript's type -system has evolved to model code written by native JavaScripters. The -resulting system is powerful, interesting and messy.
-This introduction is designed for working Haskell or ML programmers -who want to learn TypeScript. It describes how the type system of -TypeScript differs from Haskell's type system. It also describes -unique features of TypeScript's type system that arise from its -modelling of JavaScript code.
-This introduction does not cover object-oriented programming. In -practice, object-oriented programs in TypeScript are similar to those -in other popular languages with OO features.
-In this introduction, I assume you know the following:
+TypeScript는 웹에 전통적인 객체 지향 프로그램를 가져오기 위해서 +마이크로소프트 프로그래머들이 JavaScript에 전통적인 객체 지향 타입을 +가져오기 위한 시도로 시작되었습니다. 개발되어 가면서 TypeScript의 +타입 시스템은 네이티브 자바스크립터가 작성한 모델 코드로 발전되었습니다. +결과적인 시스템은 강력하면서 흥미롭고 지저분합니다.
+이 소개는 TypeScript를 배우고자 하는 Haskell 또는 ML 프로그래머를 +위해 만들어졌습니다. Haskell 타입 시스템과 TypeScript 타입 시스템의 +차이를 설명합니다. +또한 JavaScript 코드의 모델링에서 발생하는 TypeScript 타입 시스템의 +독특한 특징을 설명합니다.
+이 소개에서는 객체 지향 프로그래밍을 다루지 않습니다. +실제로, TypeScript의 객체 지향 프로그램은 OO 기능이 있는 다른 인기 언어의 +프로그램과 유사합니다.
+본 서론에서는 다음 사항을 알고 있다고 가정합니다:
If you need to learn the good parts of JavaScript, read -JavaScript: The Good Parts. -You may be able to skip the book if you know how to write programs in -a call-by-value lexically scoped language with lots of mutability and -not much else. -R4RS Scheme is a good example.
-The C++ Programming Language is
-a good place to learn about C-style type syntax. Unlike C++,
-TypeScript uses postfix types, like so: x: string
instead of string x
.
JavaScript defines 7 built-in types:
+JavaScript의 핵심 개념을 배우고 싶다면 +JavaScript: The Good Parts를 추천합니다. +많은 가변성을 가진 call-by-value 렉시컬한 스코프 언어로 +프로그램을 작성하는 방법을 알고 있다면 굳이 책을 안 읽어도 +상관없습니다. +R4RS Scheme가 좋은 예입니다.
+C++ 프로그래밍 언어는
+C-스타일 타입 구문에 대해서 배우기 좋습니다.
+C++ 달리 TypeScript는 후위 타입을 사용합니다, 예를 들면: string x
대신에 x: string
.
JavaScript에서는 7개의 내장 타입을 정의합니다:
Type | -Explanation | +타입 | +설명 |
---|---|---|---|
Number |
-a double-precision IEEE 754 floating point. | +배정밀도 IEEE 754 부동소수점. | |
String |
-an immutable UTF-16 string. | +수정 불가능한 UTF-16 문자열. | |
Boolean |
-true and false . |
+true 와 false . |
|
Symbol |
-a unique value usually used as a key. | +보통 키로 사용하는 고유한 값. | |
Null |
-equivalent to the unit type. | +단위 타입과 동등. | |
Undefined |
-also equivalent to the unit type. | +또한 단위 타입과 동등. | |
Object |
-similar to records. | +레코드와 유사한 것. |
See the MDN page for more detail.
-TypeScript has corresponding primitive types for the built-in types:
+ +TypeScript에는 기본 내장된 타입에 해당하는 원시 타입이 있습니다:
number
string
undefined
object
Type | -Explanation | +타입 | +설명 |
---|---|---|---|
unknown |
-the top type. | +최상위 타입. | |
never |
-the bottom type. | +하위 타입. | |
object literal | -eg { property: Type } |
+객체 리터럴 | +예, { property: Type } |
void |
-a subtype of undefined intended for use as a return type. |
+리턴 타입으로 사용하기 위해 의도된 undefined 의 서브타입. |
|
T[] |
-mutable arrays, also written Array<T> |
+수정가능한 배열들, 또한 Array<T> 으로 사용가능 |
|
[T, T] |
-tuples, which are fixed-length but mutable | +고정된 길이지만 수정 가능한 튜플 | |
(t: T) => U |
-functions | +함수 |
Notes:
+유의하세요:
Function syntax includes parameter names. This is pretty hard to get used to!
+함수 구문에는 매개변수 이름이 포함되어 있습니다. 익숙해지기 꽤 어렵습니다!
let fst: (a: any, d: any) => any = (a, d) => a;
-// or more precisely:
+// 또는 좀 더 정확하게 말하자면:
let snd: <T, U>(a: T, d: U) => U = (a, d) => d;
Object literal type syntax closely mirrors object literal value syntax:
+객체 리터럴 타입 구문이 객체 리터럴 값 구문과 꽤 유사합니다:
let o: { n: number; xs: object[] } = { n: 1, xs: [] };
[T, T]
is a subtype of T[]
. This is different than Haskell, where tuples are not related to lists.
[T, T]
는 T[]
의 서브타입입니다. Haskell과 달리, 튜플은 리스트와 관련이 없습니다.
JavaScript has boxed equivalents of primitive types that contain the
-methods that programmers associate with those types. TypeScript
-reflects this with, for example, the difference between the primitive
-type number
and the boxed type Number
. The boxed types are rarely
-needed, since their methods return primitives.
JavaScript는 프로그래머들이 해당 타입에 접근할 수 있는 메서드를
+포함하는 원시타입을 동등하게 박스해 왔습니다. 예를 들면, 원시 형태의
+number
과 박스 형태 타입의 Number
의 다른 점을 TypeScript는
+반영해왔습니다.
+박스 형태 타입은 메서드가 원시 타입을 반환할 때 아주 드물게 필요합니다.
(1).toExponential();
-// equivalent to
+// 동등하게
Number.prototype.toExponential.call(1);
-Note that calling a method on a numeric literal requires it to be in -parentheses to aid the parser.
-TypeScript uses the type any
whenever it can't tell what the type of
-an expression should be. Compared to Dynamic
, calling any
a type
-is an overstatement. It just turns off the type checker
-wherever it appears. For example, you can push any value into an
-any[]
without marking the value in any way:
```ts twoslash -// with "noImplicitAny": false in tsconfig.json, anys: any[] -const anys = []; -anys.push(1); -anys.push("oh no"); -anys.push({ anything: "goes" });
-
-And you can use an expression of type `any` anywhere:
-
-```ts
-anys.map(anys[1]); // oh no, "oh no" is not a function
-
any
is contagious, too — if you initialise a variable with an
-expression of type any
, the variable has type any
too.
let sepsis = anys[0] + anys[1]; // this could mean anything
+숫자 리터럴에서 메서드를 호출하려면 파서를 지원하기 위해 메서드를 괄호
+안에 넣어야 한다는 점에 유의하십시오.
+점진적인 타이핑 (Gradual typing)
+TypeScript는 표현식의 타입을 알 수 없을 때마다 any
타입을
+사용합니다. Dynamic
와 비교하면,any
는 타입이라고 부르기에
+과하다고 할 수도 있습니다.
+이 타입이 나타날 때마다 타입을 체크하지 않습니다. 예를 들어, any[]
+에 어떤 값이든 체크하지 않고 넣어도 상관없습니다:
+// tsconfig.json 파일에 "noImplicitAny": false 를 삽입, anys: any[]
+const anys = [];
+anys.push(1);
+anys.push("oh no");
+anys.push({ anything: "goes" });
-To get an error when TypeScript produces an any
, use
-"noImplicitAny": true
, or "strict": true
in tsconfig.json
.
-Structural typing
-Structural typing is a familiar concept to most functional
-programmers, although Haskell and most MLs are not
-structurally typed. Its basic form is pretty simple:
+그리고 any
타입은 어디서든 간에 사용가능합니다:
+anys.map(anys[1]); // 오 안되죠, "oh no" 함수가 아닙니다.
+
+any
전염될 수 있는데, 역시 — 만약에 any
타입의 표현식과 함께 변수를 초기화하면,
+변수 역시 any
타입을 가집니다.
+let sepsis = anys[0] + anys[1]; // 어떤 의미로도 가능합니다.
+
+TypeScript는 any
를 제공할 때 에러가 발생되면,
+tsconfig.json
에서 "noImplicitAny": true
또는 "strict": true
를 설정해야 합니다.
+구조적인 타이핑 (Structural typing)
+비록 하스켈과 대부분의 ML은 구조적으로 타이핑하지 않지만,
+구조적 타이핑은 대부분의 함수형 프로그래머에게는 익숙한 개념입니다.
+기본 형태는 아주 간단합니다:
// @strict: false
-let o = { x: "hi", extra: 1 }; // ok
-let o2: { x: string } = o; // ok
+let o = { x: "hi", extra: 1 }; // 성공
+let o2: { x: string } = o; // 성공
-Here, the object literal { x: "hi", extra: 1 }
has a matching
-literal type { x: string, extra: number }
. That
-type is assignable to { x: string }
since
-it has all the required properties and those properties have
-assignable types. The extra property doesn't prevent assignment, it
-just makes it a subtype of { x: string }
.
-Named types just give a name to a type; for assignability purposes
-there's no difference between the type alias One
and the interface
-type Two
below. They both have a property p: string
. (Type aliases
-behave differently from interfaces with respect to recursive
-definitions and type parameters, however.)
-```ts twoslash
-// @errors: 2322
-type One = { p: string };
-interface Two {
- p: string;
+
여기서, 객체 리터럴 { x: "hi", extra : 1 }
에 매치되는
+{ x : string, extra : number }
가 있습니다. 이
+타입은 필수 프로퍼티가 모두 있고 해당 프로퍼티에 할당 가능한 타입이 있으므로
+{ x : string }
에 할당할 수 있습니다.
+나머지 프로퍼티는 할당을 막지 않고, {x : string}
의 서브타입으로
+만듭니다.
+네임드 타입들은 타입에서 이름을 붙일 뿐입니다. 할당을 위해서라면 타입 별칭
+ One
과 인터페이스 타입 Two
사이에는 별 다른 점이 없습니다.
+둘 다 p: string
프로퍼티를 가지고 있습니다.
+(단, 타입 별칭은 재귀 정의와 타입 매개변수에 관련한 인터페이스에서는 다르게
+동작합니다.)
+// @errors: 2322
+type One = { p: string };
+interface Two {
+ p: string;
}
-class Three {
- p = "Hello";
-}
-let x: One = { p: "hi" };
-let two: Two = x;
-two = new Three();
-
-## Unions
-
-In TypeScript, union types are untagged. In other words, they are not
-discriminated unions like `data` in Haskell. However, you can often
-discriminate types in a union using built-in tags or other properties.
-
-```ts twoslash
-function start(
- arg: string | string[] | (() => string) | { s: string }
-): string {
- // this is super common in JavaScript
- if (typeof arg === "string") {
- return commonCase(arg);
- } else if (Array.isArray(arg)) {
- return arg.map(commonCase).join(",");
- } else if (typeof arg === "function") {
- return commonCase(arg());
- } else {
- return commonCase(arg.s);
+class Three {
+ p = "Hello";
+}
+
+let x: One = { p: "hi" };
+let two: Two = x;
+two = new Three();
+
+유니언 (Unions)
+TypeScript에서 유니언 타입은 태그되지 않습니다. 다르게 말하면,
+하스켈에서 data
와 달리 유니언은 구별하지 않습니다.
+그러나 다른 프로퍼티나 내장된 태그를 사용하는 유니언으로 타입을 구별할 수 있습니다.
+function start(
+ arg: string | string[] | (() => string) | { s: string }
+): string {
+ // JavaScript에서 아주 일반적입니다
+ if (typeof arg === "string") {
+ return commonCase(arg);
+ } else if (Array.isArray(arg)) {
+ return arg.map(commonCase).join(",");
+ } else if (typeof arg === "function") {
+ return commonCase(arg());
+ } else {
+ return commonCase(arg.s);
}
- function commonCase(s: string): string {
- // finally, just convert a string to another string
- return s;
+ function commonCase(s: string): string {
+ // 마지막으로, 다른 문자열로 변환합니다
+ return s;
}
}
-
string
, Array
and Function
have built-in type predicates,
-conveniently leaving the object type for the else
branch. It is
-possible, however, to generate unions that are difficult to
-differentiate at runtime. For new code, it's best to build only
-discriminated unions.
-The following types have built-in predicates:
+
+string
, Array
와 Function
은 타입 조건자가
+내장되어 있고, else
브랜치를 위한 객체 타입은 편의를 위해
+남겨두는 게 좋습니다.
+그러나 런타임에 구별하기 어려운 유니언을 생성할 수 있습니다.
+새로운 코드의 경우, 구별하는 유니언만 구축하는 게 가장 좋습니다.
+다음 타입들은 조건자를 가지고 있다:
-Type
-Predicate
+타입
+조건자
@@ -1341,218 +1337,202 @@ Structural typing
-Note that functions and arrays are objects at runtime, but have their
-own predicates.
-Intersections
-In addition to unions, TypeScript also has intersections:
-```ts twoslash
-type Combined = { a: number } & { b: string };
-type Conflicting = { a: number } & { a: string };
-
-`Combined` has two properties, `a` and `b`, just as if they had been
-written as one object literal type. Intersection and union are
-recursive in case of conflicts, so `Conflicting.a: number & string`.
-
-## Unit types
-
-Unit types are subtypes of primitive types that contain exactly one
-primitive value. For example, the string `"foo"` has the type
-`"foo"`. Since JavaScript has no built-in enums, it is common to use a set of
-well-known strings instead. Unions of string literal types allow
-TypeScript to type this pattern:
-
-```ts twoslash
-declare function pad(s: string, n: number, direction: "left" | "right"): string;
-pad("hi", 10, "left");
-
When needed, the compiler widens — converts to a
-supertype — the unit type to the primitive type, such as "foo"
-to string
. This happens when using mutability, which can hamper some
-uses of mutable variables:
-```ts twoslash
-// @errors: 2345
-declare function pad(s: string, n: number, direction: "left" | "right"): string;
-// ---cut---
-let s = "right";
-pad("hi", 10, s); // error: 'string' is not assignable to '"left" | "right"'
-
-Here's how the error happens:
-
-*-* `"right": "right"`
-*-* `s: string` because `"right"` widens to `string` on assignment to a mutable variable.
-*-* `string` is not assignable to `"left" | "right"`
-
-You can work around this with a type annotation for `s`, but that
-in turn prevents assignments to `s` of variables that are not of type
-`"left" | "right"`.
-
-```ts twoslash
-declare function pad(s: string, n: number, direction: "left" | "right"): string;
-// ---cut---
-let s: "left" | "right" = "right";
-pad("hi", 10, s);
-
Concepts similar to Haskell
-Contextual typing
-TypeScript has some obvious places where it can infer types, like
-variable declarations:
-```ts twoslash
-let s = "I'm a string!";
-
-But it also infers types in a few other places that you may not expect
-if you've worked with other C-syntax languages:
-
-```ts twoslash
-declare function map<T, U>(f: (t: T) => U, ts: T[]): U[];
-let sns = map((n) => n.toString(), [1, 2, 3]);
-
Here, n: number
in this example also, despite the fact that T
and U
-have not been inferred before the call. In fact, after [1,2,3]
has
-been used to infer T=number
, the return type of n => n.toString()
-is used to infer U=string
, causing sns
to have the type
-string[]
.
-Note that inference will work in any order, but intellisense will only
-work left-to-right, so TypeScript prefers to declare map
with the
-array first:
-```ts twoslash
-declare function map(ts: T[], f: (t: T) => U): U[];
-
-Contextual typing also works recursively through object literals, and
-on unit types that would otherwise be inferred as `string` or
-`number`. And it can infer return types from context:
-
-```ts twoslash
-declare function run<T>(thunk: (t: T) => void): T;
-let i: { inference: string } = run((o) => {
- o.inference = "INSERT STATE HERE";
+함수와 배열은 런타임에서 객체이지만 고유의 조건자를 가지고 있다는 걸
+기록합시다.
+교집합
+유니언과 더불어 TypeScript은 교집합까지 가지고 있습니다:
+type Combined = { a: number } & { b: string };
+type Conflicting = { a: number } & { a: string };
+
+Combined
은 마치 하나의 객체 리터럴 타입으로 작성된 것 처럼
+a
와 b
두 개의 속성을 가지고 있습니다. 교집합과 유니언은 재귀적인
+케이스에서 충돌을 일으켜서 Conflicting.a: number & string
입니다.
+유니언 타입 (Unit types)
+유니언 타입은 정확히 하나의 원시 값을 포함하고 있는 원시 타입의 서브타입입니다.
+예를 들면, 문자열 "foo"
는 타입 "foo"
를 가지고 있습니다.
+JavaScript는 내장된 enum이 없기 때문에 잘 알려진 문자열 세트를
+대신해서 쓰는게 흔합니다.
+문자열 리터럴 타입 유니언은 TypeScript에서 이 패턴을 따라갑니다:
+declare function pad(s: string, n: number, direction: "left" | "right"): string;
+pad("hi", 10, "left");
+
+필요한 경우에 컴파일러로 확장가능합니다_ — 상위 타입으로
+변환합니다 — 원시 타입에서 유닛 타입으로, string
에서 "foo"
으로
+수정가능할 때 일어나며, 수정가능한 변수를 일부 사용할 때 제대로
+동작하지 않을 수 있습니다:
+// @errors: 2345
+declare function pad(s: string, n: number, direction: "left" | "right"): string;
+// ---cut---
+let s = "right";
+pad("hi", 10, s); // 오류: 'string'은 '"left" | "right"'에 할당할 수 없습니다.
+
+이런 에러가 나타날 수 있습니다:
+- "right": "right"
+- s: string
은 "right"
가 수정가능한 변수에 할당될 때 string
으로 확장이 가능합니다.
+- string
은 "left" | "right"
에 할당할 수 없습니다.
+s
에 타입 표기를 사용하여 해결 가능하지만,
+그 결과 "left" | "right"
타입이 아닌 변수가
+s
에 할당되는 것을 방지하게 됩니다.
+declare function pad(s: string, n: number, direction: "left" | "right"): string;
+// ---cut---
+let s: "left" | "right" = "right";
+pad("hi", 10, s);
+
+Haskell과 비슷한 개념 (Concepts similar to Haskell)
+문맥적인 타이핑 (Contextual typing)
+TypeScript는 변수 선언과 같이 타입을 추론할 수 있는
+몇 가지 분명한 방법이 있습니다:
+let s = "I'm a string!";
+
+하지만 다른 C-계열 언어로 작업한 적이 있다면 예상하지 못했던
+다른 방법으로 타입 추론이 가능합니다:
+declare function map<T, U>(f: (t: T) => U, ts: T[]): U[];
+let sns = map((n) => n.toString(), [1, 2, 3]);
+
+여기에서, 이 예시의 n: number
에서 또한, T
과 U
는 호출 전에
+추론되지 않았음에도 불구하고.
+실제로 [1,2,3]
으로 T=number
을 추론한 다음에,
+n => n.toString()
의 리턴 타입으로 U=string
을 추론하여,
+sns
가 string[]
타입을 가지도록 합니다.
+추론은 어떤 순서로든 작동하지만, intellisense는 왼쪽에서 오른쪽으로만
+작동하므로, TypeScript는 배열과 함께 map
을 먼저 선언하는 것을
+선호합니다:
+declare function map<T, U>(ts: T[], f: (t: T) => U): U[];
+
+문맥적인 타이핑은 또한 객체 리터럴을 통해 재귀적으로 작동하며, 그렇지 않으면
+string
이나 number
로 추론 가능한 유닛 타입으로 작동합니다.
+그리고 문맥을 통해서 리턴 타입을 추론할 수 있습니다:
+declare function run<T>(thunk: (t: T) => void): T;
+let i: { inference: string } = run((o) => {
+ o.inference = "INSERT STATE HERE";
});
-
The type of o
is determined to be { inference: string }
because
+
+o
의 타입은 { inference: string }
으로 결정되었습니다. 왜냐하면
-- Declaration initialisers are contextually typed by the
-declaration's type:
{ inference: string }
.
-- The return type of a call uses the contextual type for inferences,
-so the compiler infers that
T={ inference: string }
.
-- Arrow functions use the contextual type to type their parameters,
-so the compiler gives
o: { inference: string }
.
+- 선언 이니셜라이저는 선언 타입:
{ inference: string }
에 따라서
+문맥적으로 타입이 정해집니다.
+- 호출의 리턴 타입은 추론을 위해 문맥적인 타입을 사용하기 때문에,
+컴파일러는
T={ inference: string }
으로 추론합니다.
+- 화살표 함수는 매개변수에 타입을 지정하기 위해 문맥적인 타입을 사용하므로,
+컴파일러는
o: { inference: string }
를 제공합니다.
-And it does so while you are typing, so that after typing o.
, you
-get completions for the property inference
, along with any other
-properties you'd have in a real program.
-Altogether, this feature can make TypeScript's inference look a bit
-like a unifying type inference engine, but it is not.
-Type aliases
-Type aliases are mere aliases, just like type
in Haskell. The
-compiler will attempt to use the alias name wherever it was used in
-the source code, but does not always succeed.
-```ts twoslash
-type Size = [number, number];
-let x: Size = [101.1, 999.9];
-
-The closest equivalent to `newtype` is a _tagged intersection_:
-
-```ts
-type FString = string & { __compileTimeOnly: any };
-
An FString
is just like a normal string, except that the compiler
-thinks it has a property named __compileTimeOnly
that doesn't
-actually exist. This means that FString
can still be assigned to
-string
, but not the other way round.
-Discriminated Unions
-The closest equivalent to data
is a union of types with discriminant
-properties, normally called discriminated unions in TypeScript:
+입력하는 동안, o.
를 타이핑 후에,
+실제 프로그램에 있는 다른 속성과 함께 속성 inference
으로
+보완할 수 있습니다.
+이 기능은 TypeScript의 추론을 통해 통합적인 타입 추론 엔진처럼
+보이겠지만, 그렇지 않습니다.
+타입 별칭 (Type aliases)
+타입 별칭은 Haskell의 type
과 마찬가지로 단순한 별칭입니다.
+컴파일러는 소스 코드에서 사용된 별칭 이름을 사용하려고
+시도하지만 항상 성공하지는 않습니다.
+type Size = [number, number];
+let x: Size = [101.1, 999.9];
+
+newtype
과 가장 유사한 것은 태그된 교차 타입(tagged intersection) 입니다:
+type FString = string & { __compileTimeOnly: any };
+
+FString
은 컴파일러가 실제로는 존재하지 않는 __compileTimeOnly
라는
+프로퍼티를 가지고 있다고 생각하는 점을 제외하면 일반 문자열과 같습니다.
+FString
은 여전히 string
에 할당 가능하지만,
+그 반대는 불가능하다는 것을 의미합니다.
+판별 유니언 (Discriminated Unions)
+data
와 가장 유사한 것은 보통 TypeScript에서 판별 유니언이라 불리는,
+ 판별 프로퍼티를 갖는 타입의 유니언입니다:
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; x: number }
| { kind: "triangle"; x: number; y: number };
-Unlike Haskell, the tag, or discriminant, is just a property in each
-object type. Each variant has an identical property with a different
-unit type. This is still a normal union type; the leading |
is
-an optional part of the union type syntax. You can discriminate the
-members of the union using normal JavaScript code:
-```ts twoslash
-type Shape =
- | { kind: "circle"; radius: number }
- | { kind: "square"; x: number }
- | { kind: "triangle"; x: number; y: number };
-function area(s: Shape) {
- if (s.kind === "circle") {
- return Math.PI s.radius s.radius;
- } else if (s.kind === "square") {
- return s.x s.x;
- } else {
- return (s.x s.y) / 2;
+
하스켈과 달리, 태그 또는 판별은 각각 객체 타입에서 단지 속성에 불구합니다.
+특이 케이스는 다른 유닛 타입과 함께 동일한 속성을 가집니다.
+아직 평범한 유니언타입입니다; 리드하는 |
는
+유니언 타입 구문의 선택적인 부분입니다. 유니언을 사용하는 평범한 JavaScript
+코드로 구별가능합니다:
+type Shape =
+ | { kind: "circle"; radius: number }
+ | { kind: "square"; x: number }
+ | { kind: "triangle"; x: number; y: number };
+
+function area(s: Shape) {
+ if (s.kind === "circle") {
+ return Math.PI * s.radius * s.radius;
+ } else if (s.kind === "square") {
+ return s.x * s.x;
+ } else {
+ return (s.x * s.y) / 2;
}
-}
-
-Note that the return type of `area` is inferred to be `number` because
-TypeScript knows the function is total. If some variant is not
-covered, the return type of `area` will be `number | undefined` instead.
-
-Also, unlike Haskell, common properties show up in any union, so you
-can usefully discriminate multiple members of the union:
-
-```ts twoslash
-type Shape =
- | { kind: "circle"; radius: number }
- | { kind: "square"; x: number }
- | { kind: "triangle"; x: number; y: number };
-// ---cut---
-function height(s: Shape) {
- if (s.kind === "circle") {
- return 2 * s.radius;
- } else {
- // s.kind: "square" | "triangle"
- return s.x;
+}
+
+area
의 리턴 타입은 number
를 나타내는데, TypeScript가 함수가 전체라는
+걸 알고 있기 때문에 유의해야할 필요가 있습니다. 몇몇 특이 케이스가 커버되지 않으면
+area
의 리턴 타입은 number | undefined
으로 대신될 것입니다.
+또한, 하스켈과 달리 흔한 속성들은 어떤 유니언에도 나타나며,
+그래서 유용하게 여러 개의 유니언 구분가능합니다:
+type Shape =
+ | { kind: "circle"; radius: number }
+ | { kind: "square"; x: number }
+ | { kind: "triangle"; x: number; y: number };
+// ---cut---
+function height(s: Shape) {
+ if (s.kind === "circle") {
+ return 2 * s.radius;
+ } else {
+ // s.kind: "square" | "triangle"
+ return s.x;
}
}
-
Type Parameters
-Like most C-descended languages, TypeScript requires declaration of
-type parameters:
+
+타입 매개변수 (Type Parameters)
+대부분의 C-계열 언어처럼, TypeScript는 타입 매개변수의 선언을
+요구합니다:
function liftArray<T>(t: T): Array<T> {
return [t];
}
-There is no case requirement, but type parameters are conventionally
-single uppercase letters. Type parameters can also be constrained to a
-type, which behaves a bit like type class constraints:
+대소문자에 대한 요구 조건은 없지만, 타입 매개 변수는 일반적으로 단일 대문자입니다.
+타입 매개 변수는 타입 클래스 제약과 비슷하게 동작하는
+타입으로 제한될 수 있습니다.
function firstish<T extends { length: number }>(t1: T, t2: T): T {
return t1.length > t2.length ? t1 : t2;
}
-TypeScript can usually infer type arguments from a call based on the
-type of the arguments, so type arguments are usually not needed.
-Because TypeScript is structural, it doesn't need type parameters as
-much as nominal systems. Specifically, they are not needed to make a
-function polymorphic. Type parameters should only be used to
-propagate type information, such as constraining parameters to be
-the same type:
+TypeScript는 일반적으로 인자 타입에 기반하여 호출로부터 타입 인자를 추론할 수 있기 때문에
+대게 타입 인자를 필요로 하지 않습니다.
+왜냐하면 TypeScript는 구조적이기 때문에, 이름 기반의 시스템만큼 타입 매개 변수를 필요로
+하지 않습니다. 특히 함수를 다형성으로 만들
+필요는 없습니다. 타입 매개변수는 매개변수를 같은 타입으로
+제한하는 것처럼 타입 정보를 전파하는데만
+쓰여야 합니다:
function length<T extends ArrayLike<unknown>>(t: T): number {}
function length(t: ArrayLike<unknown>): number {}
-In the first length
, T is not necessary; notice that it's only
-referenced once, so it's not being used to constrain the type of the
-return value or other parameters.
-Higher-kinded types
-TypeScript does not have higher kinded types, so the following is not legal:
+첫 번째 length
에서 T는 필요하지 않습니다; 오직 한 번만 참조되며,
+다른 매개변수나 리턴 값의 타입을 제한하는데 사용되지 않는다는 것을
+알아둬야 합니다.
+상위 유형의 타입 (Higher-kinded types)
+TypeScript는 상위 유형의 타입이 없습니다. 그러므로 다음과 같이 하는 건 허용하지 않습니다:
function length<T extends ArrayLike<unknown>, U>(m: T<U>) {}
-Point-free programming
-Point-free programming — heavy use of currying and function
-composition — is possible in JavaScript, but can be verbose.
-In TypeScript, type inference often fails for point-free programs, so
-you'll end up specifying type parameters instead of value parameters. The
-result is so verbose that it's usually better to avoid point-free
-programming.
-Module system
-JavaScript's modern module syntax is a bit like Haskell's, except that
-any file with import
or export
is implicitly a module:
+포인트-프리 프로그래밍 (Point-free programming)
+포인트-프리 프로그래밍은 — 커링 및 함수 합성의 과도한 사용
+— JavaScript에서 가능하지만 장황할 수 있습니다.
+TypeScript에서 포인트-프리 프로그래밍에 대한 타입 추론이 실패하는 경우가 많으므로,
+값 매개변수 대신 타입 매개변수를 지정하게 됩니다.
+그 결과는 너무 장황해서 보통 포인트-프리 프로그래밍은 피하는 게
+좋습니다.
+모듈 시스템 (Module system)
+import
또는 export
가 포함된 파일이 암시적으로 모듈이라는 점을 제외하면
+JavaScript의 최신 모듈 구문은 Haskell과 약간 유사합니다:
import { value, Type } from "npm-package";
import { other, Types } from "./local-package";
import * as prefix from "../lib/third-package";
-You can also import commonjs modules — modules written using node.js'
-module system:
+commonjs 모듈로 가져올 수 있습니다 — node.js' 모듈 시스템으로
+사용된 모듈:
import f = require("single-function-package");
-You can export with an export list:
+export 목록으로 내보낼 수 있습니다:
export { f };
function f() {
@@ -1560,55 +1540,55 @@ Module system
}
function g() {} // g is not exported
-Or by marking each export individually:
+또는 개별적으로 표시해서:
export function f { return g() }
function g() { }
-The latter style is more common but both are allowed, even in the same
-file.
-readonly
and const
-In JavaScript, mutability is the default, although it allows variable
-declarations with const
to declare that the reference is
-immutable. The referent is still mutable:
+후자의 스타일이 더 일반적이지만 같은 파일 내에서도 둘 다
+허용됩니다.
+readonly
와 const
(readonly
and const
)
+JavaScript에서, 수정 가능함이 기본이지만,
+참조가 수정 불가능함을 선언하기 위해 const
로 변수를 선언할 수 있습니다.
+참조 대상은 여전히 수정 가능합니다:
const a = [1, 2, 3];
a.push(102); // ):
a[0] = 101; // D:
-TypeScript additionally has a readonly
modifier for properties.
+TypeScript는 추가적으로 프로퍼티에 readonly
제어자를 사용할 수 있습니다.
interface Rx {
readonly x: number;
}
let rx: Rx = { x: 1 };
rx.x = 12; // error
-It also ships with a mapped type Readonly<T>
that makes
-all properties readonly
:
+매핑된 타입 Readonly<T>
은 모든 프로퍼티를 readonly
으로
+만들어 버립니다:
interface X {
x: number;
}
let rx: Readonly<X> = { x: 1 };
rx.x = 12; // error
-And it has a specific ReadonlyArray<T>
type that removes
-side-affecting methods and prevents writing to indices of the array,
-as well as special syntax for this type:
+그리고 부작용을 일으키는 메서드를 제거하고 배열 인덱스에 대한 변경을 방지하는
+특정 ReadonlyArray<T>
타입과,
+이 타입에 대한 특수 구문이 있습니다:
let a: ReadonlyArray<number> = [1, 2, 3];
let b: readonly number[] = [1, 2, 3];
a.push(102); // error
b[0] = 101; // error
-You can also use a const-assertion, which operates on arrays and
-object literals:
+배열과 객체 리터럴에서 동작하는 const-assertion만
+사용할 수 있습니다:
let a = [1, 2, 3] as const;
a.push(102); // error
a[0] = 101; // error
-However, none of these options are the default, so they are not
-consistently used in TypeScript code.
-Next Steps
-This doc is a high level overview of the syntax and types you would use in everyday code. From here you should:
-- Read the full Handbook from start to finish (30m)
-- Explore the Playground examples.
+그러나 이러한 기능들은 기본적인 기능이 아니므로 TypeScript 코드에
+일관적으로 사용하지 않아도 됩니다.
+다음 단계 (Next Steps)
+이 문서는 일상적인 코드에서 높은 수준의 구문과 타입에 대한 개요를 담고 있습니다. 여기서부터는 아래를 참고하시면 됩니다:
+- 전체 핸드북을 처음부터 끝까지 읽으세요 (30m)
+- Playground 예시를 보세요.
type MyBool = true | false;
+
+_참고:_ `MyBool`위에 마우스를 올린다면, `boolean`으로 분류된 것을 볼 수 있습니다 - 구조적 타입 시스템의 프로퍼티며, 나중에 살펴보겠습니다.
-```ts twoslash
-type MyBool = true | false;
-
Note: If you hover over MyBool
above, you'll see that it is classed as boolean
- that's a property of the Structural Type System, which we'll get to later.
One of the most popular use-cases for union types is to describe a set of string
s or number
s literal which a value is allowed to be:
```ts twoslash -type WindowStates = "open" | "closed" | "minimized"; +유니언 타입이 가장 많이 사용된 사례 중 하나는 값이 다음과 같이 허용되는 `string` 또는 `number`의 [리터럴](/docs/handbook/literal-types.html)집합을 설명하는 것입니다: +
type WindowStates = "open" | "closed" | "minimized"; type LockStates = "locked" | "unlocked"; type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
-Unions provide a way to handle different types too, for example you may have a function which accepts an `array` or a `string`.
-
-```ts twoslash
-function getLength(obj: string | string[]) {
+유니언은 다양한 타입을 처리하는 방법을 제공하는데, 예를 들어 `array` 또는 `string`을 받는 함수가 있을 수 있습니다.
+
function getLength(obj: string | string[]) { return obj.length; -} -
TypeScript understands how code changes what the variable could be with time, you can use these checks to narrow the type down.
-Type | -Predicate | -
---|---|
string | -typeof s === "string" |
-
number | -typeof n === "number" |
-
boolean | -typeof b === "boolean" |
-
undefined | -typeof undefined === "undefined" |
-
function | -typeof f === "function" |
-
array | -Array.isArray(a) |
-
For example, you could differentiate between a string
and an array
, using typeof obj === "string"
and TypeScript will know what the object is down different code paths.
```ts twoslash -function wrapInArray(obj: string | string[]) { +}
+
+TypeScript는 코드가 시간에 따라 변수가 변경되는 방식을 이해하며, 이러한 검사를 사용해 타입을 골라낼 수 있습니다.
+
+| Type | Predicate |
+| --------- | ---------------------------------- |
+| string | `typeof s === "string"` |
+| number | `typeof n === "number"` |
+| boolean | `typeof b === "boolean"` |
+| undefined | `typeof undefined === "undefined"` |
+| function | `typeof f === "function"` |
+| array | `Array.isArray(a)` |
+
+예를 들어, `typeof obj === "string"`을 이용하여 `string`과 `array`를 구분할 수 있으며 TypeScript는 객체가 다른 코드 경로에 있음을 알게 됩니다.
+
+<!-- prettier-ignore -->
+
function wrapInArray(obj: string | string[]) { if (typeof obj === "string") { return [obj]; // ^? @@ -1230,40 +1204,36 @@
-### Generics
+### 제네릭 (Generics)
-You can get very deep into the TypeScript generic system, but at a 1 minute high-level explanation, generics are a way to provide variables to types.
+TypeScript 제네릭 시스템에 대해 자세히 알아볼 수 있지만, 1분 정도의 수준 높은 설명을 하기 위해, 제네릭은 타입에 변수를 제공하는 방법입니다.
-A common example is an array, an array without generics could contain anything. An array with generics can describe what values are inside in the array.
+배열이 일반적인 예시이며, 제네릭이 없는 배열은 어떤 것이든 포함할 수 있습니다. 제네릭이 있는 배열은 배열 안의 값을 설명할 수 있습니다.
```ts
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;
-
You can declare your own types which use generics:
-```ts twoslash
-// @errors: 2345
-interface Backpack 제네릭을 사용하는 고유 타입을 선언할 수 있습니다:// @errors: 2345
+interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
-}
// This line is a shortcut to tell TypeScript there is a
-// constant called backpack
, and to not worry about where it came from
-declare const backpack: Backpack
// object is a string, because we declared it above as the variable part of Backpack -const object = backpack.get();
-// Due to backpack variable being a string, you cannot pass a number to the add function -backpack.add(23);
-
-## Structural Type System
+}
-One of TypeScript's core principles is that type checking focuses on the _shape_ which values have.
-This is sometimes called "duck typing" or "structural typing".
+// 이 줄은 TypeScript에 `backpack`이라는 상수가 있음을 알리는 지름길이며
+// const backpakc: Backpack<string>이 어디서 왔는지 걱정할 필요가 없습니다.
-In a structural type system if two objects have the same shape, they are considered the same.
+// 위에서 Backpack의 변수 부분으로 선언해서, object는 string입니다.
+const object = backpack.get();
-```ts twoslash
-interface Point {
+// backpack 변수가 string이므로, add 함수에 number를 전달할 수 없습니다.
+backpack.add(23);
+
TypeScript의 핵심 원칙 중 하나는 타입 검사가 값이 있는 형태에 집중한다는 것입니다. +이는 때때로 "덕 타이핑(duck typing)" 또는 "구조적 타이핑" 이라고 불립니다.
+구조적 타입 시스템에서 두 객체가 같은 형태를 가지면 같은 것으로 간주됩니다.
+interface Point {
x: number;
y: number;
}
@@ -1272,33 +1242,33 @@ 타입 &
console.log(`${p.x}, ${p.y}`);
}
-// prints "12, 26"
+// "12, 26"를 출력합니다
const point = { x: 12, y: 26 };
printPoint(point);
-
The point
variable is never declared to be a Point
type, but TypeScript compares the shape of point
to the shape of Point
in the type-check.
-Because they both have the same shape, then it passes.
The shape matching only requires a subset of the object's fields to match.
-```ts twoslash -// @errors: 2345 +
point
변수는 Point
타입으로 선언된 적이 없지만, TypeScript는 타입 검사에서 point
의 형태와 Point
의 형태를 비교합니다.
+둘 다 같은 형태이기 때문에, 통과합니다.
형태 일치에는 일치시킬 객체의 필드의 하위 집합만 필요합니다.
+// @errors: 2345
interface Point {
x: number;
y: number;
-}
-function printPoint(p: Point) {
- console.log(${p.x}, ${p.y}
);
+}
+
+function printPoint(p: Point) {
+ console.log(`${p.x}, ${p.y}`);
}
// ---cut---
const point3 = { x: 12, y: 26, z: 89 };
-printPoint(point3); // prints "12, 26"
-const rect = { x: 33, y: 3, width: 30, height: 80 };
-printPoint(rect); // prints "33, 3"
-const color = { hex: "#187ABF" };
-printPoint(color);
-
-Finally, to really nail this point down, structurally there is no difference between how classes and objects conform to shapes:
+printPoint(point3); // prints "12, 26"
-```ts twoslash
-// @errors: 2345
+const rect = { x: 33, y: 3, width: 30, height: 80 };
+printPoint(rect); // prints "33, 3"
+
+const color = { hex: "#187ABF" };
+
+printPoint(color);
+
마지막으로, 정확하게 마무리 짓기 위해, 구조적으로 클래스와 객체가 형태를 따르는 방법에는 차이가 없습니다:
+// @errors: 2345
interface Point {
x: number;
y: number;
@@ -1320,12 +1290,12 @@ 타입 &
const newVPoint = new VirtualPoint(13, 56);
printPoint(newVPoint); // prints "13, 56"
-
If the object or class has all the required properties, then TypeScript will say they match regardless of the implementation details.
-Next Steps
-This doc is a high level 5 minute overview of the sort of syntax and tools you would use in everyday code. From here you should:
+
객체 또는 클래스에 필요한 모든 속성이 존재한다면, TypeScript는 구현 세부 정보에 관계없이 일치하게 봅니다.
+해당 문서는 일상적인 코드에서 사용하는 구문 및 도구의 종류에 대한 수준 높은 5분 개요입니다. 여기에서: