Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Korean] Fix weird expressions like '_제네릭_' #171

Merged
merged 2 commits into from
Oct 4, 2022

Conversation

Joy1590
Copy link
Contributor

@Joy1590 Joy1590 commented Sep 28, 2022

Fix #167

@github-actions
Copy link
Contributor

Thanks for the PR!

This section of the codebase is owned by @bumkeyy, @yeonjuan, @guyeol, and @dvlprsh - if they write a comment saying "LGTM" then it will be merged.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 28, 2022

Translation of DOM Manipulation.md

title: DOM Manipulation
layout: docs
permalink: /ko/docs/handbook/dom-manipulation.html
oneline: Using the DOM with TypeScript

translatable: true

DOM Manipulation

HTMLElement Type Exploration (An exploration into the HTMLElement type)

In the more than 20 years since its standardization, JavaScript has made great progress. JavaScript will also be available for servers, data science, and IoT devices in 2020, but it's important to remember that the most popular use case is a web browser.

A website consists of HTML and/or XML documents. These documents are static and do not change. The Document Object Model (DOM) is a A programming interface implemented by a browser to make a static website work functionally. The DOM API allows you to change the structure, style, and content of a document. The API is so powerful that numerous front-end frameworks (jQuery, React, Angular, etc.) have been developed to make it easier to develop dynamic websites.

TypeScript is a JavaScript superset with types, and provides type definitions for the DOM API. These definitions are readily available in all native TypeScript projects. lib.dom.d.ts Of the more than 20,000 lines of definitions in , the most striking is HTMLElementIs. This type is the backbone of DOM manipulation using TypeScript.

DOM Type DefinitionThe source code for can be found here.

Basic Example

A simple example file index.html:

<!DOCTYPE html>
<html lang="en">
  <head><title>TypeScript Dom Manipulation</title></head>
  <body>
    <div id="app"></div>
    <!-- Assume index.js is the compiled output of index.ts -->
    <script src="index.js"></script>
  </body>
</html>

#app On the Elements <p>Hello, World</p> Let's look at a TypeScript script to add elements.

// 1. id 프로퍼티를 사용하여 div 요소를 선택합니다.
const app = document.getElementById("app");

// 2. 새로운 <p></p> 요소를 프로그래밍 방식으로 생성합니다.
const p = document.createElement("p");

// 3. 텍스트 내용을 추가합니다.
p.textContent = "Hello, World!";

// 4. div 요소에 p 요소를 자식 노드로 추가합니다.
app?.appendChild(p);

index.html After compiling and running the page, the HTML result:

<div id="app">
  <p>Hello, World!</p>
</div>

Document The interface (The Document Interface)

The first line of TypeScript code is a global variable document, and if you examine that variable, lib.dom.d.ts of the file Document It is marked as defined by the interface. The snippet of that code has getElementByIdand createElementcontains two method calls:

Document.getElementById

This method is defined as follows:

getElementById(elementId: string): HTMLElement | null;

If the string id element is passed HTMLElement or nullThis is returned. This method is one of the most important types: HTMLElementto introduce. This type serves as the base interface for all other element interfaces. For example, in the example code, p The variable is HTMLParagraphElement Type. Next, this method is nullIt is important to note that you can return . This is because the method cannot be a definitive pre-runtime depending on whether it can actually find the specified element or not. On the last line of the snippet code, appendChildNew to call Optional chaining An operator is being used.

Document.createElement

This method is defined as follows (deprecated The denoted definition was omitted):

createElement<K extends keyof HTMLElementTagNameMap>(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K];
createElement(tagName: string, options?: ElementCreationOptions): HTMLElement;

This is an overloaded function definition. The second overload is the simplest, getElementById It works very similarly to the method. How 문자열If passed, the HTMLElement standard is returned. This definition allows developers to generate their own HTML element tags.

Like what document.createElement('xyz')is not an element specified in HTML conformance <xyz></xyz> Returns an element.

For those who are interested, to mention, document.getElementsByTagNameYou can use to interact with custom tag elements.

createElementThe first definition of uses advanced generic patterns. This is best understood by dividing the content. first <K extends keyof HTMLElementTagNameMap>Start with a generic representation of the name. This expression is HTMLElementTagNameMap Generic parameters that are constrained by the keys of the interface Kis defined. That map interface contains all the specified HTML tag names and corresponding type interfaces. For example, here are 5 mapped values at the beginning of the code:

interface HTMLElementTagNameMap {
    "a": HTMLAnchorElement;
    "abbr": HTMLElement;
    "address": HTMLElement;
    "applet": HTMLAppletElement;
    "area": HTMLAreaElement;
        ...
}

Some elements do not exhibit unique properties. HTMLElementHowever, other type elements have their own properties and methods and have specific interfaces (HTMLElementextended or implemented in ).

now createElement The rest of the definition, (tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]Let's take a look. First argument tagNameis a generic parameter Kis defined as: The TypeScript interpreter uses generic parameters from this argument to inference It has enough performance to do it. This means that developers don't actually need to specify generic parameters when using the method, and what value is tagNameWhether passed as an argument or not KIt will be inferred as such, so it should be available for the rest of the definition. If you look at exactly what is happening, the return value HTMLElementTagNameMap[K]The tagNameTake an argument and return that type. This definition is in the snippet code p In a variable HTMLParagraphElementIt's a way to get the type. And the code is document.createElement('a')Were HTMLAnchorElementIt becomes an element of type.

Node The interface (The Node interface)

document.getElementById The function is HTMLElementReturns the . HTMLElement The interface is Node Extended Interface Element Expand Interfaces. These prototype extensions are all HTMLElementsallows you to take advantage of a subset of the standard methods. In the code snippet Node Using the attributes defined in the interface to create a new website p element.

Node.appendChild

The last line of the code snippet is app?.appendChild(p)Is. Previous section (document.getElementById) in appBecause it is likely to be null at this runtime Optional chaining I explained that the operator is used here. appendChildThe method of is as follows:

appendChild<T extends Node>(newChild: T): T;

Generic Parameters Tprice newChild Because it comes from an argument, this method is createElement It works similarly to the method. Tis another main interface, 노드rho _restriction_Is.

childrenand childNodesDifference between children and childNodes)

Previously, this article was HTMLElement Interface NodeExpanded from ElementI explained that it is an extended concept in . The DOM API has Children There is a concept of elements. For example, in HTML p Tagged with div A child of the element.

<div>
  <p>Hello, World</p>
  <p>TypeScript!</p>
</div>;

const div = document.getElementByTagName("div")[0];

div.children;
// HTMLCollection(2) [p, p]

div.childNodes;
// NodeList(2) [p, p]

div After you find the element, click children Properties are HTMLParagraphElementsIncluding the HTMLCollection Returns a list. childNodes The property is a node list similar to the above. NodeListReturns the . each p The tag is still HTMLParagraphElements Although it is a type, NodeListIn addition to the HTMLCollection Not on the list HTML Node can include

p Modify the html by removing one of the tags, but keep the text intact.

<div>
  <p>Hello, World</p>
  TypeScript!
</div>;

const div = document.getElementByTagName("div")[0];

div.children;
// HTMLCOllection(1) [p]

div.childNodes;
// NodeList(2) [p, text]

Let's see how the two lists have changed. childrenis currently <p>Hello, World</p> contains only elements, childNodesThere are two p Non-node text Contains nodes. NodeListIn text Part TypeScript! Literal containing text NodeIs. children The list is this NodeDoes not include: because HTMLElementThis is because it is not considered to be.

querySelectorand querySelectorAll Method (The querySelector and querySelectorAll methods)

Both methods are good tools for getting a list of dome elements that fit into a unique set of constraints. The methods are lib.dom.d.ts is defined as follows:

/**
 * 선택자와 일치하는 노드의 자식 중 첫 번째 요소를 반환합니다.
 */
querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
querySelector<E extends Element = Element>(selectors: string): E | null;

/**
 * 선택자와 일치하는 모든 노드 자식 요소를 반환합니다.
 */
querySelectorAll<K extends keyof HTMLElementTagNameMap>(selectors: K): NodeListOf<HTMLElementTagNameMap[K]>;
querySelectorAll<K extends keyof SVGElementTagNameMap>(selectors: K): NodeListOf<SVGElementTagNameMap[K]>;
querySelectorAll<E extends Element = Element>(selectors: string): NodeListOf<E>;

querySelectorAll The definition is NodeListOfExcept that it returns a new type of getElementByTagNameSimilar to . This return type is basically a custom implementation of a standard JavaScript list element. NodeListOf<E> E[]Replacing with will arguably provide a very similar user experience. NodeListOfThe length , item(index), forEach((value, key, parent) => void) , and only implements properties and methods, such as creating numeric indices. Also, the method is node and not element Returns a list, which means .childNodes Method NodeListis returned. It may seem like a contradiction, but Element The interface is NodeIt is important to note that it has been extended from .

To see the two methods work, modify the existing code as follows:

<ul>
  <li>First :)</li>
  <li>Second!</li>
  <li>Third times a charm.</li>
</ul>;

const first = document.querySelector("li"); // 첫 번째 li 요소를 반환합니다.
const all = document.querySelectorAll("li"); // 모든 li 요소를 포함하는 리스트를 반환합니다.

Want to know more? (Interested in learning more?)

lib.dom.d.ts The best part about the type definition is that it reflects the types listed on the Mozilla Developer Network (MDN) documentation site. For example HTMLElement The interface is from MDN HTMLElement pageis documented in. This page provides all the available properties, methods, and sometimes even examples. The other great aspect of the page is that it provides links that fit into the standard documentation. Here's how to W3C Recommendations for HTMLElementHere's a link to:

See source code:

Translation of Babel with TypeScript.md

title: Using Babel with TypeScript
layout: docs
permalink: /ko/docs/handbook/babel-with-typescript.html
oneline: How to create a hybrid Babel + TypeScript project

translatable: true

Babel vs TypeScript tsc

When you create a modern JavaScript project, you might be thinking about the correct way to convert from TypeScript to JavaScript files.

In many cases the answer depends on the project "Depends on" or "Someone may have decided on your behalf' will be. What if tsdx, Angular, NestJSor an existing framework such as Getting StartedIf you are creating a project using the framework mentioned in , this decision will be handled automatically for you.

However, here's an intuitive way to use:

  • Are the build output results and source input files pretty much the same? tscUse .
  • Do you need a build pipeline that produces multiple potential deliverables? babelTranspiling with , tscCheck the type with .

Transpiling is Babel, the type is tsc

This is a common pattern for projects with existing build infrastructure that may have been ported from the JavaScript code base to TypeScript.

This technique, by Babel preset-typescriptto generate a JS file, and then use TypeScript to check for type and .d.ts This is a compound approach to generating files.

Because Babel supports TypeScript, you can work with existing build pipelines and JS output times can be faster because Babel doesn't inspect code types.

Type checking and d.ts file generation

The downside of using Babel is that you can't do type checking while switching TS to JS. This means that type errors that you don't catch in the editor may be included in your production code.

Also, Babel for TypeScript .d.ts Because you can't create files, it can be harder to work with if your project is a library.

To resolve these issues, we recommend that you set up a command that allows you to use TSC to check the type of the project. This is part of the Babel configuration. tsconfig.jsonThis means replicating to and verifying that the following flags are enabled:

"compilerOptions": {
  // tsc를 사용해 .js 파일이 아닌 .d.ts 파일이 생성되었는지 확인합니다.
  "declaration": true,
  "emitDeclarationOnly": true,
  // Babel이 TypeScript 프로젝트의 파일을 안전하게 트랜스파일할 수 있는지 확인합니다.
  "isolatedModules": true
}

For more information on these flags, please refer to the following:

Translation of TypeScript 4.0.md

title: TypeScript 4.0
layout: docs
permalink: /ko/docs/handbook/release-notes/typescript-4-0.html

oneline: TypeScript 4.0 Release Notes

Variadic Tuple Types

In JavaScript by combining two arrays or tuple types to create a new array concat Let's think about functions.

function concat(arr1, arr2) {
  return [...arr1, ...arr2];
}

Then, an array or tuple is entered as a variable and returns the remainder except for the first element. tail Let's also think about functions.

function tail(arg) {
  const [_, ...result] = arg;
  return result;
}

How can TypeScript define the types of these two functions?

concatIn the case of , in previous versions the only way to create multiple overloads was to create them.

function concat(arr1: [], arr2: []): [];
function concat<A>(arr1: [A], arr2: []): [A];
function concat<A, B>(arr1: [A, B], arr2: []): [A, B];
function concat<A, B, C>(arr1: [A, B, C], arr2: []): [A, B, C];
function concat<A, B, C, D>(arr1: [A, B, C, D], arr2: []): [A, B, C, D];
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];)

Sound... Yes, the second array of these overloads is all empty.
At this time, arr2Let's add a case where has one argument.

function concat<A2>(arr1: [], arr2: [A2]): [A2];
function concat<A1, A2>(arr1: [A1], arr2: [A2]): [A1, A2];
function concat<A1, B1, A2>(arr1: [A1, B1], arr2: [A2]): [A1, B1, A2];
function concat<A1, B1, C1, A2>(arr1: [A1, B1, C1], arr2: [A2]): [A1, B1, C1, A2];
function concat<A1, B1, C1, D1, A2>(arr1: [A1, B1, C1, D1], arr2: [A2]): [A1, B1, C1, D1, A2];
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];

These overloading functions are clearly irrational.
Unfortunately tail When you type a function, you face a similar problem.

This is one case of "death by a thousand overloads", and it doesn't even solve most of the problems.
It only provides the correct type for as many overloads as we want to write.
If you want to create a comprehensive case, you need the following overload:

function concat<T, U>(arr1: T[], arr2: U[]): Array<T | U>;

However, the above signature doesn't handle anything about the input path or the order of the elements when using tuples.

TypeScript 4.0 introduces two key changes, including improved type reasoning, to make this typing possible.

The first change is that you can use generic types in the spread operator in the tuple type syntax.
This means that even if we don't know the actual type that works, we can still express higher-order functions for tuples and arrays.
In these tuple types, when the generic spread operator is instantiated (or replaced by a real type), another set of array or tuple types can be produced.

For example tail You will be able to type the same function without the "death by a thousand overloads" issue.

function tail<T extends any[]>(arr: readonly [any, ...T]) {
  const [_ignored, ...rest] = arr;
  return rest;
}

const myTuple = [1, 2, 3, 4] as const;
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 the remaining elements can occur anywhere in the 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 had generated the following error:

A rest element must be last in a tuple type.

TypeScript 4.0 eased this limitation.

When trying to extend a type that is not of a fixed length, keep in mind that the type of the result is not limited, and all of the following elements are included in the remaining element types of the result:

type Strings = [string, string];
type Numbers = number[];

type Unbounded = [...Strings, ...Numbers, boolean];
//   ^ = type Unbounded = [string, string, ...(number | boolean)[]]

By combining these two actions together, concatYou can create a signature with a well-defined type for .

type Arr = readonly any[];

function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
  return [...arr1, ...arr2];
}

Even if one signature is a little long, it's just one signature that doesn't need to be repeated, and provides predictable behavior across all arrays and tuples.

This feature is great in itself, but it shines through in a slightly more sophisticated scenario.
For examplePartially applying the parameters of the function to return a new function partialCall Let's say you have a function.
partialCallhas the following functions: - fWith a few arguments to expect fLet's specify
After that, fhas other arguments that it still needs, when it receives fReturns a new function that calls .

function partialCall(f, ...headArgs) {
  return (...tailArgs) => f(...headArgs, ...tailArgs);
}

TypeScript 4.0 improves the inference process for the remaining parameters and tuple elements so that you can specify types and "just make them work".

type Arr = readonly unknown[];

function partialCall<T extends Arr, U extends Arr, R>(
  f: (...args: [...T, ...U]) => R,
  ...headArgs: T
) {
  return (...tailArgs: U) => f(...headArgs, ...tailArgs);
}

In this case, partialCallidentifies parameters that can and cannot be taken initially, and returns functions that accept and reject the remaining ones appropriately.

// @errors: 2345 2554 2554 2345
type Arr = readonly unknown[];

function partialCall<T extends Arr, U extends Arr, R>(
  f: (...args: [...T, ...U]) => R,
  ...headArgs: T
) {
  return (...tailArgs: U) => f(...headArgs, ...tailArgs);
}
// ---cut---
const foo = (x: string, y: number, z: boolean) => {};

const f1 = partialCall(foo, 100);

const f2 = partialCall(foo, "hello", 100, true, "oops");

// 작동합니다!
const f3 = partialCall(foo, "hello");
//    ^ = const f3: (y: number, z: boolean) => void

// f3으로 뭘 할 수 있을까요?

// 작동합니다!
f3(123, true);

f3();

f3(123, "hello");

Variable factor tuple types enable many new interesting patterns, especially when it comes to functional construction.
We have JavaScript built into bind I expect to be able to take advantage of this to better check the type of the method.
Several other reasoning improvements and patterns are also included here, and if you want to learn more about variable factor tuples, the pull requestSee .

Labeled Tuple Elements

Improving on tuple types and parameter lists is important because it strengthens type validation against common JavaScript idioms - you just need to actually truncate the argument list and pass it to another function.
The idea that you can use a tuple type for the rest parameter is very important.

For example, the following function, which takes the tuple type as the remaining parameter, is...

function foo(...args: [string, number]): void {
  // ...
}

... It should not be different from the following functions...

function foo(arg0: string, arg1: number): void {
  // ...
}

...fooFor all callers of the too.

// @errors: 2554
function foo(arg0: string, arg1: number): void {
  // ...
}
// ---cut---
foo("hello", 42);

foo("hello", 42, true);
foo("hello");

But where I'm starting to see the difference is: readability.
In the first example, there are no parameter names for the first and second elements.
There is no effect on type-checking, but the absence of a label in the tuple position makes it difficult to use - it is difficult to convey intent.

That's why TypeScript 4.0 provides labels for tuple types.

type Range = [start: number, end: number];

To strengthen the connection between the parameter list and the tuple type, the syntax for the remaining elements and optional elements reflects the syntax of the parameter list.

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 the other elements in the tuple must also be labeled.

// @errors: 5084
type Bar = [first: string, number];

Understandably - labels don't need to specify variable names differently when destructuring.
This is purely necessary for documentation and tools.

function foo(x: [first: string, second: number]) {
    // ...

    // 주의: 'first'와 'second'에 대해 이름 지을 필요 없음
    const [a, b] = x;
    a
//  ^ = const a: string
    b
//  ^ = const b: number
}

Overall, labeled tuples come in handy when implementing overloading in a safe type manner and when utilizing patterns in tuples and argument lists.
In fact, TypeScript Editor support tries to mark it as overloaded when possible.

라벨링된 튜플의 유니언을 매개변수 목록에서처럼 두 가지 시그니처로 보여주는 시그니처 도움말

If you want to know more, about labeled tuple elements Pull RequestCheck it out

Class Property Inference from Constructors

In TypeScript 4.0, noImplicitAnyWhen is enabled, you can use control flow analysis to determine the property type within a class.

class Square {
  // 이전에 any로 추론했습니다.
  area;
// ^?
  sideLength;
// ^?
  constructor(sideLength: number) {
    this.sideLength = sideLength;
    this.area = sideLength ** 2;
  }
}

If not all paths in the constructor are assigned to instance members, the property is potentially undefinedwill be.

// @errors: 2532
class Square {
  sideLength;
// ^?

  constructor(sideLength: number) {
    if (Math.random()) {
      this.sideLength = sideLength;
    }
  }

  get area() {
    return this.sideLength ** 2;
  }
}

If you have more content (e.g. initialize If there are methods, etc.), strictPropertyInitialization In mode, a deterministic assignment affirmation (!) to explicitly declare the type.

class Square {
  // 확정적 할당 단언
  //        v
  sideLength!: number;
  //         ^^^^^^^^
  // 타입 표기

  constructor(sideLength: number) {
    this.initialize(sideLength);
  }

  initialize(sideLength: number) {
    this.sideLength = sideLength;
  }

  get area() {
    return this.sideLength ** 2;
  }
}

If you want to know more, Look at the pull request that runs the code.

Short-Circuiting Assignment Operators

JavaScript and many languages are compound assignment It supports a set of operators called operators.
A compound assignment operator applies an operator to two arguments and then assigns the result to the left.
You may have seen something like the following before:

// 덧셈
// a = a + b
a += b;

// 뺄셈
// a = a - b
a -= b;

// 곱셈
// a = a * b
a *= b;

// 나눗셈
// a = a / b
a /= b;

// 지수화
// a = a ** b
a **= b;

// 왼쪽 비트 시프트
// a = a << b
a <<= b;

Many operators in JavaScript have assignment operators like the one above!
But until recently, logic and Operator (&&), logic or Operator (||) and operators that merge things like null (nullish coalescing) (??) were three notable exceptions.

This is why TypeScript 4.0 is a new assignment operator&&=,||=and??=That's why it supports the new ECMAScript feature to add it.

These operators are useful for replacing any examples where you can write code like this:

a = a && b;
a = a || b;
a = a ?? b;

or similar to the following: if bloc

// 'a ||= b'로 대체 가능
if (!a) {
  a = b;
}

There are also code patterns that we have seen (or written ourselves) that are intended to deferred initialize values only when necessary.

let values: string[];
(values ?? (values = [])).push("hello");

// 이후
(values ??= []).push("hello");

(Look, written by us all I'm not proud of the code...)

In rare cases, when using getters or setters with side-effects, it is important to note that these operators perform assignments only when necessary.
In that sense, not only is the right side of the operator "short-circuited", but so is the assignment itself.

obj.prop ||= foo();

// 다음 중 하나와 대략 동일함

obj.prop || (obj.prop = foo());

if (!obj.prop) {
    obj.prop = foo();
}

Try the following example Through an example All the time See how it differs from performing assignments.

const obj = {
    get prop() {
        console.log("getter has run");

        // 이곳을 바꿔보세요!
        return Math.random() < 0.5;
    },
    set prop(_val: boolean) {
        console.log("setter has run");
    }
};

function foo() {
    console.log("right side evaluated");
    return true;
}

console.log("This one always runs the setter");
obj.prop = obj.prop || foo();

console.log("This one *sometimes* runs the setter");
obj.prop ||= foo();

Community members who have contributed Wenlu Wang I would like to express my great gratitude to you.

For more information, see Check out this Pull Request.
You can also find this feature in the TC39 Proposal repository..

unknown on catch Clause Bindings

Since the beginning days of TypeScript, catch clause variables have always been typed as any.
This meant that TypeScript allowed you to do anything you wanted with them.

try {
  // Do some work
} catch (x) {
  // x has type 'any' - have fun!
  console.log(x.message);
  console.log(x.toUpperCase());
  x++;
  x.yadda.yadda.yadda();
}

The above has some undesirable behavior if we're trying to prevent more errors from happening in our error-handling code!
Because these variables have the type any by default, they lack any type-safety which could have errored on invalid operations.

That's why TypeScript 4.0 now lets you specify the type of catch clause variables as unknown instead.
unknown is safer than any because it reminds us that we need to perform some sorts of type-checks before operating on our values.

// @errors: 2571
try {
  // ...
} catch (e: unknown) {
  // Can't access values on unknowns
  console.log(e.toUpperCase());

  if (typeof e === "string") {
    // We've narrowed 'e' down to the type 'string'.
    console.log(e.toUpperCase());
  }
}

While the types of catch variables won't change by default, we might consider a new --strict mode flag in the future so that users can opt in to this behavior.
In the meantime, it should be possible to write a lint rule to force catch variables to have an explicit annotation of either : any or : unknown.

For more details you can peek at the changes for this feature.

Custom JSX Factories

When using JSX, a fragment is a type of JSX element that allows us to return multiple child elements.
When we first implemented fragments in TypeScript, we didn't have a great idea about how other libraries would utilize them.
Nowadays most other libraries that encourage using JSX and support fragments have a similar API shape.

In TypeScript 4.0, users can customize the fragment factory through the new jsxFragmentFactory option.

As an example, the following tsconfig.json file tells TypeScript to transform JSX in a way compatible with React, but switches each factory invocation to h instead of React.createElement, and uses Fragment instead of React.Fragment.

{
  compilerOptions: {
    target: "esnext",
    module: "commonjs",
    jsx: "react",
    jsxFactory: "h",
    jsxFragmentFactory: "Fragment",
  },
}

In cases where you need to have a different JSX factory on a per-file basis, you can take advantage of the new /** @jsxFrag */ pragma comment.
For example, the following...

// @noErrors
// Note: these pragma comments need to be written
// with a JSDoc-style multiline syntax to take effect.

/** @jsx h */
/** @jsxFrag Fragment */

import { h, Fragment } from "preact";

export const Header = (
  <>
    <h1>Welcome</h1>
  </>
);

... will get transformed to this output JavaScript...

// @noErrors
// @showEmit
// Note: these pragma comments need to be written
// with a JSDoc-style multiline syntax to take effect.

/** @jsx h */
/** @jsxFrag Fragment */

import { h, Fragment } from "preact";

export const Header = (
  <>
    <h1>Welcome</h1>
  </>
);

We'd like to extend a big thanks to community member Noj Vek for sending this pull request and patiently working with our team on it.

You can see that the pull request for more details!

Speed Improvements in build mode with --noEmitOnError

Previously, compiling a program after a previous compile with errors under --incremental would be extremely slow when using the --noEmitOnError flag.
This is because none of the information from the last compilation would be cached in a .tsbuildinfo file based on the --noEmitOnError flag.

TypeScript 4.0 changes this which gives a great speed boost in these scenarios, and in turn improves --build mode scenarios (which imply both --incremental and --noEmitOnError).

For details, read up more on the pull request.

--incremental with --noEmit

TypeScript 4.0 allows us to use the --noEmit flag when while still leveraging --incremental compiles.
This was previously not allowed, as --incremental needs to emit a .tsbuildinfo files; however, the use-case to enable faster incremental builds is important enough to enable for all users.

For more details, you can see the implementing pull request.

Editor Improvements

The TypeScript compiler doesn't only power the editing experience for TypeScript itself in most major editors - it also powers the JavaScript experience in the Visual Studio family of editors and more.
For that reason, much of our work focuses on improving editor scenarios - the place you spend most of your time as a developer.

Using new TypeScript/JavaScript functionality in your editor will differ depending on your editor, but

You can check out a partial list of editors that have support for TypeScript to learn more about whether your favorite editor has support to use new versions.

Convert to Optional Chaining

Optional chaining is a recent feature that's received a lot of love.
That's why TypeScript 4.0 brings a new refactoring to convert common patterns to take advantage of optional chaining and nullish coalescing!

Converting `a && a.b.c && a.b.c.d.e.f()` to `a?.b.c?.d.e.f.()`

Keep in mind that while this refactoring doesn't perfectly capture the same behavior due to subtleties with truthiness/falsiness in JavaScript, we believe it should capture the intent for most use-cases, especially when TypeScript has more precise knowledge of your types.

For more details, check out the pull request for this feature.

/** @deprecated */ Support

TypeScript's editing support now recognizes when a declaration has been marked with a /** @deprecated * JSDoc comment.
That information is surfaced in completion lists and as a suggestion diagnostic that editors can handle specially.
In an editor like VS Code, deprecated values are typically displayed a strike-though style like this.

Some examples of deprecated declarations with strikethrough text in the editor

This new functionality is available thanks to Wenlu Wang.
See the pull request for more details.

Partial Semantic Mode at Startup

We've heard a lot from users suffering from long startup times, especially on bigger projects.
The culprit is usually a process called program construction.
This is the process of starting with an initial set of root files, parsing them, finding their dependencies, parsing those dependencies, finding those dependencies' dependencies, and so on.
The bigger your project is, the longer you'll have to wait before you can get basic editor operations like go-to-definition or quick info.

That's why we've been working on a new mode for editors to provide a partial experience until the full language service experience has loaded up.
The core idea is that editors can run a lightweight partial server that only looks at the current files that the editor has open.

It's hard to say precisely what sorts of improvements you'll see, but anecdotally, it used to take anywhere between 20 seconds to a minute before TypeScript would become fully responsive on the Visual Studio Code codebase.
In contrast, our new partial semantic mode seems to bring that delay down to just a few seconds.
As an example, in the following video, you can see two side-by-side editors with TypeScript 3.9 running on the left and TypeScript 4.0 running on the right.

When restarting both editors on a particularly large codebase, the one with TypeScript 3.9 can't provide completions or quick info at all.
On the other hand, the editor with TypeScript 4.0 can immediately give us a rich experience in the current file we're editing, despite loading the full project in the background.

Currently the only editor that supports this mode is Visual Studio Code which has some UX improvements coming up in Visual Studio Code Insiders.
We recognize that this experience may still have room for polish in UX and functionality, and we have a list of improvements in mind.
We're looking for more feedback on what you think might be useful.

For more information, you can see the original proposal, the implementing pull request, along with the follow-up meta issue.

Smarter Auto-Imports

Auto-import is a fantastic feature that makes coding a lot easier; however, every time auto-import doesn't seem to work, it can throw users off a lot.
One specific issue that we heard from users was that auto-imports didn't work on dependencies that were written in TypeScript - that is, until they wrote at least one explicit import somewhere else in their project.

Why would auto-imports work for @types packages, but not for packages that ship their own types?
It turns out that auto-imports only work on packages your project already includes.
Because TypeScript has some quirky defaults that automatically add packages in node_modules/@types to your project, those packages would be auto-imported.
On the other hand, other packages were excluded because crawling through all your node_modules packages can be really expensive.

All of this leads to a pretty lousy getting started experience for when you're trying to auto-import something that you've just installed but haven't used yet.

TypeScript 4.0 now does a little extra work in editor scenarios to include the packages you've listed in your package.json's dependencies (and peerDependencies) fields.
The information from these packages is only used to improve auto-imports, and doesn't change anything else like type-checking.
This allows us to provide auto-imports for all of your dependencies that have types, without incurring the cost of a complete node_modules search.

In the rare cases when your package.json lists more than ten typed dependencies that haven't been imported yet, this feature automatically disables itself to prevent slow project loading.
To force the feature to work, or to disable it entirely, you should be able to configure your editor.
For Visual Studio Code, this is the "Include Package JSON Auto Imports" (or typescript.preferences.includePackageJsonAutoImports) setting.

Configuring 'include package JSON auto imports'
For more details, you can see the proposal issue along with the implementing pull request.

Our New Website

The TypeScript website has recently been rewritten from the ground up and rolled out!

A screenshot of the new TypeScript website

We already wrote a bit about our new site, so you can read up more there; but it's worth mentioning that we're still looking to hear what you think!
If you have questions, comments, or suggestions, you can file them over on the website's issue tracker.

Breaking Changes

lib.d.ts Changes

Our lib.d.ts declarations have changed - most specifically, types for the DOM have changed.
The most notable change may be the removal of document.origin which only worked in old versions of IE and Safari
MDN recommends moving to self.origin.

Properties Overriding Accessors (and vice versa) is an Error

Previously, it was only an error for properties to override accessors, or accessors to override properties, when using useDefineForClassFields; however, TypeScript now always issues an error when declaring a property in a derived class that would override a getter or setter in the base class.

// @errors: 1049 2610
class Base {
  get foo() {
    return 100;
  }
  set foo(value) {
    // ...
  }
}

class Derived extends Base {
  foo = 10;
}
// @errors: 2611
class Base {
  prop = 10;
}

class Derived extends Base {
  get prop() {
    return 100;
  }
}

See more details on the implementing pull request.

Operands for delete must be optional

When using the delete operator in strictNullChecks, the operand must now be any, unknown, never, or be optional (in that it contains undefined in the type).
Otherwise, use of the delete operator is an error.

// @errors: 2790
interface Thing {
  prop: string;
}

function f(x: Thing) {
  delete x.prop;
}

See more details on the implementing pull request.

Usage of TypeScript's Node Factory is Deprecated

Today TypeScript provides a set of "factory" functions for producing AST Nodes; however, TypeScript 4.0 provides a new node factory API.
As a result, for TypeScript 4.0 we've made the decision to deprecate these older functions in favor of the new ones.

For more details, read up on the relevant pull request for this change.

Translation of Triple-Slash Directives.md

title: Triple-Slash Directives
layout: docs
permalink: /ko/docs/handbook/triple-slash-directives.html
oneline: How to use triple slash directives in TypeScript

translatable: true

A triple-slash directive is a single-line comment that contains a single XML tag.
The contents of the comments are used as compiler directives.

The triple-slash directive is only Valid only at the top of the embedded file.
Triple-slash directives, including other triple-slash directives, can only be in front of a single or multiline comment.
If it follows a statement or declaration, it is usually considered a one-line comment and does not have any special meaning.

/// <reference path="..." />

/// <reference path="..." />Directives are the most common triple-slash directives.
This directive is between files Dependency Used as a declaration.

A triple-slash reference tells the compiler to include additional files in the compilation process.

In addition --outor --outFileWhen using , it is used as a method to sort the output.
The files are created in the output file location in the same order as the inputs after the pre-processing.

Preprocessing input files

The compiler performs preprocessing on the input file to analyze all triple-slash reference directives.
During this process, additional files are added to the compilation.

The process is root files It starts from a set;
This root file is located on the command line or tsconfig.jsonof the file "files" The name of the file in the list.
These files are preprocessed in the order specified.
Before adding a file to the list, all triple-slash references in the file are processed and their targets are included.
Triple-slash references are treated as depth-first in the order they appear in the file.

If there is no root, the triple-slash reference path is treated relative to the file containing it.

Errors

Referencing a file that does not exist is an error.
Files that have a triple-slash reference to themselves are errors.

--noResolve Using --noResolve)

Compiler Flags --noResolveIf specified, triple-slash references are ignored; It does not add new files or change the order of the supplied files.

/// <reference types="..." />

Dependency Acting as a declaration /// <reference path="..." /> Similar to directives, /// <reference types="..." /> The directive declares the dependencies of the package.

The process of handling package names is importIt's similar to the process of handling module names in a statement.
Triple-slash-reference-type directive declaration of the package importIt's easy to understand if you think about it.

For example, in a declaration file /// <reference types="node" />Including: @types/node/index.d.tsis to use the name declared in ;
Therefore, this package must be included in the compilation along with the declaration file.

This directive is d.ts Use it only when you write your own files.

For declaration files generated during compilation, the compiler automatically /// <reference types="..." />Add the ;
/// <reference types="..." />is appended inside the generated file only if the resulting file uses the declared statement of the referenced package.

.ts From the file @types To declare a package's dependencies, from the command line --typesor tsconfig.jsonUse .
using @types, typeRoots and types in tsconfig.json files Check out the details here.

/// <reference lib="..." />

This directive states that the file is explicitly built into the existing lib Have them include the file.

viscera lib The file is _tsconfig.json_of "lib" It is referenced in the same way as compiler options (yes.lib="lib.es2015.d.ts" and not lib="es2015" use, etc.).

For authors of declaration files that rely on built-in types, it is recommended to use the triple-slash-reference lib directive (built-in types: DOM APIs, or Symbolor Iterable(previously, these .d.ts files should have added this type of forward/duplicate declaration.

For example, in compilation to one of the files /// <reference lib="es2017.string" />The addition of is --lib es2017.stringIt's like compiling with

/// <reference lib="es2017.string" />

"foo".padStart(4);

/// <reference no-default-lib="true"/>

This directive allows you to use the file _Default Library_is displayed.
lib.d.tsand variations of it at the top.

This directive is based on the compiler base library (for example. lib.d.ts) in compilation Avoid Instruct.
On the command line --noLibIt has a similar effect to handing over .

In addition --skipDefaultLibCheckIf you hand it over, the compiler will /// <reference no-default-lib="true"/>Note that files with are not scanned.

/// <amd-module />

By default, AMD modules are created anonymously.
This means that other tools in the process of creating it into a module (e.g. r.js) can cause problems.

amd-module The directive allows you to optionally pass the module name to the compiler:

amdModule.ts
///<amd-module name="NamedModule"/>
export class C {}

define As part of the call NamedModule It will give you the result of assigning a name to the module:

amdModule.js
define("NamedModule", ["require", "exports"], function (require, exports) {
  var C = (function () {
    function C() {}
    return C;
  })();
  exports.C = C;
});

/// <amd-dependency />

Note: This directive has been deprecated. minister import "moduleName"; Use the door.

/// <amd-dependency path="x" />tells the compiler about the dependencies of the non-TS module that should be added to the resulting module's require call.

The amd-dependency The directive is optionally name will have properties; This allows you to optionally pass the name to amd-dependency:

/// <amd-dependency path="legacy/moduleA" name="moduleA"/>
declare var moduleA: MyType;
moduleA.callStuff();

Generated JS code:

define(["require", "exports", "legacy/moduleA"], function (
  require,
  exports,
  moduleA
) {
  moduleA.callStuff();
});
Translation of Namespaces and Modules.md

title: Namespaces and Modules
layout: docs
permalink: /ko/docs/handbook/namespaces-and-modules.html
oneline: How to organize code in TypeScript via modules or namespaces

translatable: true

This article outlines the various ways to organize your code using modules and namespaces in TypeScript.
We'll also explore some advanced topics about namespaces and modules, as well as the common dangers encountered when using namespaces and modules in TypeScript.

For more information about ES modules, see module See the documentation.
For more information about TypeScript namespaces, see Namespace See the documentation.

Consultation: Very much Older versions of the TypeScript namespace were formerly called 'Internal Modules', a JavaScript module system.

Using Modules

A module can contain both code and declarations.

Modules also have dependencies on the module loader (such as CommonJs/Require.js) or runtimes supported by ES modules.
Modules provide enhanced tools for greater code reusability, stronger isolation and bundling.

It's also important to note that for Node.js applications, modules are the primary approach, and the recommended approach to structuring your code.

Starting with ECMAScript 2015, modules are an intrinsic part of the language, and all compatible engine implementations must support the module.
Therefore, for new projects, modules are recommended as a way to organize your code.

Using Namespaces

Namespaces are TypeScript's unique way of organizing code.
The namespace is simply named as a JavaScript object in the global namespace.
This makes it possible to use namespaces as a very simple structure.
Unlike modules, they can encompass multiple files. --outFileYou can connect using .
Namespaces are a great way to structure code in a web application, and all dependencies are part of an HTML page. <script> Include it as a tag.

Especially for large applications, this approach can make it difficult to identify a component's dependencies, as would if all global namespaces were contaminated.

Pitfalls of Namespaces and Modules

Here we will discuss the various risks that often arise when using namespaces and modules, and their solutions.

/// <reference>Modules using

Common mistakes to refer to module files importInstead of a door /// <reference ... /> It's about using syntax.
To understand the difference between the two, first of all import You need to understand how the compiler finds type information for modules that are located in the path. (For example, import x from "...";, import x = require("..."); In the back ...)

The compiler is .ts, .tsxand then locate the appropriate path .d.tsLocate .
If it doesn't find a specific file, the compiler will _Declaration of ambient module_will explore.
.d.ts Remember to declare these in the file.

  • myModules.d.ts

    // 모듈이 아닌 .d.ts 파일 또는 .ts 파일:
    declare module "SomeModule" {
        export function fn(): string;
    }
  • myOtherModule.ts

    /// <reference path="myModules.d.ts" />
    import * as m from "SomeModule";

The reference tag above is required to specify the location of the declaration file that contains the ambient module declaration.
This method is used by several TypeScript samples. node.d.tsHow to use the file.

Needless Namespacing

If you change a program that used to use the namespace to a module, the file is likely to look something like this:

  • shapes.ts

    export namespace Shapes {
        export class Triangle { /* ... */ }
        export class Square { /* ... */ }
    }

Top-level modules Shapesmeans nothing Triangleand SquareWraps around it.
This causes confusion and annoyance among module users:

  • shapeConsumer.ts

    import * as shapes from "./shapes";
    let t = new shapes.Shapes.Triangle(); // shapes.Shapes?

One of the important features of the TypeScript module is that two different modules never provide names within the same scope.
Because the module user decides which name to assign, there is no need to pre-wrap the emitted symbol inside the namespace.

The reason why you don't need to set a namespace for a module's contents is that the general purpose of specifying a namespace is to provide a logical group of structures and to avoid name conflicts.
Because the module files already form logical groups of their own, the top-level names are defined by the code that imports them, and there is no need to use an additional module hierarchy for the objects being exported.

The following is an example of a modification:

  • shapes.ts

    export class Triangle { /* ... */ }
    export class Square { /* ... */ }
  • shapeConsumer.ts

    import * as shapes from "./shapes";
    let t = new shapes.Triangle();

Trade-offs of Modules

Just as JS files and modules have one-to-one correspondence, TypeScript has a one-to-one correspondence between the module source files and the JS files generated from them.
Because of these characteristics, depending on which module system you are using, it may not be possible to merge multiple module source files.
For example commonjs or umdWhile targeting the outFile The option is not available, but since TypeScript 1.8, amd or systemIf you are targeting outFile Options it is now available.

Translation of JSX.md

title: JSX
layout: docs
permalink: /ko/docs/handbook/jsx.html
oneline: Using JSX with TypeScript

translatable: true

JSXis an embedded syntax similar to XML.
This means that the conversion will vary depending on the implementation, but it must be converted to valid JavaScript.
JSX React It gained popularity as a framework, but other implementations have since emerged.
TypeScript supports embedding, type checking, and JXX compiling directly into JavaScript.

Basic usage method

Before using JSX, you need to do two things:

  1. .tsx Naming files with extensions
  2. jsx Activate options

TypeScript provides three JSX modes: preserve, react, react-native.
This mode only affects the output step, not the type check.
preserve The mode keeps JSX as part of the output, so that it can be used in other conversion steps (for example, Babel) in addition.
Also, the output file extension is .jsxIs.
react The mode is React.createElementand don't have to go through JSX conversion before using , and the output file extension is .jsIs.
react-native Mode in that it preserves all JSX preserve Similar to the mode, but with an output file extension .jsThere is a difference.

mode input output Output File Extension
preserve <div /> <div /> .jsx
react <div /> React.createElement("div") .js
react-native <div /> <div /> .js
react-jsx <div /> _jsx("div", {}, void 0); .js
react-jsxdev <div /> _jsxDEV("div", {}, void 0, false, {...}, this); .js

--jsx Command line flag or tsconfig.json In a file jsxYou can set the mode through the corresponding options in .

*Consultation: --jsxFactory You can use the options to specify which JSX factory function to use when releasing React JSX. (The default is React.createElement)

as operator

Here's how to write a type assertion:

var foo = <foo>bar;

This is a variable barprice foo Affirm to have a type.
TypeScript also uses angle brackets for assertions, so combining it with the syntax of JSX can cause difficulty in parsing certain things. As a result, TypeScript is .tsxDoes not allow angle bracket type affirmations in files.

This syntax is .tsx Since it cannot be used in a file, the alternative type assertion operator asmust be used.
as You can easily rewrite the above example using operators.

var foo = bar as foo;

as The operator is .tsand .tsx Valid for all files of the format, the angle bracket type assertion style and behavior are the same.

Type checking

To understand type checking with JSX, you must first understand the difference between built-in and value-based elements.
<expr />Given the JSX expression, expris an element built into the environment, such as the DOM environment. div or span ) or a custom component.
Two reasons why this is important are:

  1. In React, built-in elements are strings (React.createElement("div")) but the components it produces are (React.createElement(MyComponent)) not.
  2. The type of attribute passed to a JSX element must be looked up differently.
    The attributes of the built-in elements are Implicitly As it should be, components want to specify their own set of properties.

TypeScript uses this to distinguish between them. React-like rulesUse .
Built-in elements always start with lowercase letters, and value-based elements always start with uppercase letters.

Built-in elements

The built-in element is a special interface. JSX.IntrinsicElementsis looked up in .
Basically, if no interface is specified, it will proceed as is, and the built-in functions will not have type checking.
However, if this interface is which If the name of the built-in function is JSX.IntrinsicElements It is queried by the properties in the interface.
For example:

declare namespace JSX {
  interface IntrinsicElements {
    foo: any;
  }
}

<foo />; // 성공
<bar />; // 오류

In the example above, <foo />works normally, <bar />The JSX.IntrinsicElementsThe error occurs because it is not specified in .

Note: As below JSX.IntrinsicElementsYou can also specify a catch-all string indexer in .

declare namespace JSX {
  interface IntrinsicElements {
    [elemName: string]: any;
  }
}

Value-based elements

Value-based elements are simply looked up by identifiers within their scopes.

import MyComponent from "./myComponent";

<MyComponent />; // 성공
<SomeOtherComponent />; // 오류

There are two ways to define a value-based element:

  1. Functional Components (FC)
  2. Class Components

Since the two types of value-based elements are indistinguishable from JSX representations, TS first interprets the representation as a functional component using overload resolution. If successful, TS completes interpreting the expression on the declaration. If the value is not resolved to a functional component, TS interprets it as a class component. If that fails, TS reports an error.

Functional Components

As the name implies, a component has a first argument props It is defined as a JavaScript function that is an object.
TS returns the type JSX.Elementmust be assignable to .

interface FooProp {
  name: string;
  X: number;
  Y: number;
}

declare function AnotherComponent(prop: { name: string });
function ComponentFoo(prop: FooProp) {
  return <AnotherComponent name={prop.name} />;
}

const Button = (prop: { value: string }, context: { color: string }) => (
  <button />
);

Functional components are JavaScript functions, so they can be overloaded:

interface ClickableProps {
  children: JSX.Element[] | JSX.Element
}

interface HomeProps extends ClickableProps {
  home: JSX.Element;
}

interface SideProps extends ClickableProps {
  side: JSX.Element | string;
}

function MainButton(prop: HomeProps): JSX.Element;
function MainButton(prop: SideProps): JSX.Element {
  ...
}

Note: Functional components are known as stateless functional components (SFCs). Recent versions of React no longer consider functional components to be stateless. SFC Type and its aliases StatelessComponent is deprecated anymore.

Class Components

It is also possible to define a class component type.
But to do that, Element class type and _Element instance type_It's good to understand the two terms:

<Expr />Given the , _Element Class Types_silver ExprType.
So, in the example above, MyComponentIf is an ES6 class, the type of that class is the constructor of the class and is global.
What if MyComponentIf is a factory function, the type of that class is that function.

Once the type of the class is determined, the instance type is determined by the creation of the class type or the combination of the return type of the calling signature (whichever of the two exists).
Again, for ES6 classes, the instance type must be the type of the instance of that class, and for factory functions, it must be the type of the value returned by the function.

class MyComponent {
  render() {}
}

// 생성 시그니처 사용
var myComponent = new MyComponent();

// 요소 클래스 타입 => MyComponent
// 요소 인스턴스 타입 => { render: () => void }

function MyFactoryFunction() {
  return {
    render: () => {},
  };
}

// 호출 시그니처 사용
var myComponent = MyFactoryFunction();

// 요소 클래스 타입 => FactoryFunction
// 요소 인스턴스 타입 => { render: () => void }

The element instance type is JSX.ElementClassmust be assignable to , or an error will be thrown.
By default JSX.ElementClassThe {}However, it can be extended to restrict the use of JSX to only types that follow the appropriate interface.

declare namespace JSX {
  interface ElementClass {
    render: any;
  }
}

class MyComponent {
  render() {}
}
function MyFactoryFunction() {
  return { render: () => {} };
}

<MyComponent />; // 성공
<MyFactoryFunction />; // 성공

class NotAValidComponent {}
function NotAValidFactoryFunction() {
  return {};
}

<NotAValidComponent />; // 오류
<NotAValidFactoryFunction />; // 오류

Attribute Type Inspection

For attribute type checking, first _Element attribute type_You need to decide.
This is a slight difference between built-in and value-based elements.

For built-in elements, the element attribute type is JSX.IntrinsicElements This is the type of my property.

declare namespace JSX {
  interface IntrinsicElements {
    foo: { bar?: boolean };
  }
}

// 'foo'의 요소 속성 타입은 '{bar?: boolean}'
<foo bar />;

For value-based elements, this is slightly more complicated.
The element attribute type was previously determined Element Instance Type is determined by the property type of .
The properties to use are JSX.ElementAttributesPropertyis determined by:
It must be declared as a single property.
After that, use the name of that property.
Starting with TypeScript 2.8 JSX.ElementAttributesProperty If you do not provide , you can use the type of the first parameter of the call to the class element or the functional component's name instead.

declare namespace JSX {
  interface ElementAttributesProperty {
    props; // 사용할 프로퍼티 이름 지정
  }
}

class MyComponent {
  // 요소 인스턴스 타입의 프로퍼티 지정
  props: {
    foo?: string;
  };
}

// 'MyComponent'의 요소 속성 타입은 '{foo?: string}'
<MyComponent foo="bar" />;

Element attribute types are used for type checking of attributes in JSX.
Optional and essential properties are supported.

declare namespace JSX {
  interface IntrinsicElements {
    foo: { requiredProp: string; optionalProp?: number };
  }
}

<foo requiredProp="bar" />; // 성공
<foo requiredProp="bar" optionalProp={0} />; // 성공
<foo />; // 오류, requiredProp이 누락됨
<foo requiredProp={0} />; // 오류, requiredProp은 문자열이여야 함
<foo requiredProp="bar" unknownProp />; // 오류, unknownProp는 존재하지 않음
<foo requiredProp="bar" some-unknown-prop />; // 성공, 'some-unknown-prop'는 유효한 식별자가 아니기 때문

Note: An identifier whose name of the attribute is valid (data-* attributes, etc.), if the element attribute type cannot be found, it is not considered an error.

Additional JSX.IntrinsicAttributes Interfaces can specify additional properties for use of the JSX framework, which is not typically used as props or arguments to components. - For example React key. Further, JSX.IntrinsicClassAttributes<T> Generic types can also be specified in the same way as the types of additional attributes for class components (functional components are not). For that type, the generic parameter corresponds to a class instance type. In React, Ref<T>Types of ref Used to accept attributes. In general, if users of the JSX framework do not need to provide specific attributes to all tags, all properties of this interface should be optional.

The spread operator also works:

var props = { requiredProp: "bar" };
<foo {...props} />; // 성공

var badProps = {};
<foo {...badProps} />; // 오류

Child type checking

Starting with TypeScript 2.3, TS Children Introduced type checking. _child_Silver git _JSXExpressions_What you want to insert into this property _Element attribute type_is a special property of .
TS props To determine the name JSX.ElementAttributesPropertySimilar to using the TS, TS child To determine the name of props within JSX.ElementChildrenAttributeUse .
JSX.ElementChildrenAttribute must be defined as a single property.

declare namespace JSX {
  interface ElementChildrenAttribute {
    children: {}; // 사용할 자식의 이름을 지정
  }
}
<div>
  <h1>Hello</h1>
</div>;

<div>
  <h1>Hello</h1>
  World
</div>;

const CustomComp = (props) => <div>{props.children}</div>
<CustomComp>
  <div>Hello World</div>
  {"This is just a JS expression..." + 1000}
</CustomComp>

Like any other property_child_You can also specify the type of . For example, React typingIf you use , this will override the base type.

interface PropsType {
  children: JSX.Element
  name: string
}

class Component extends React.Component<PropsType, {}> {
  render() {
    return (
      <h2>
        {this.props.children}
      </h2>
    )
  }
}

// OK
<Component name="foo">
  <h1>Hello World</h1>
</Component>

// 오류: 자식은 JSX.Element의 배열이 아닌 JSX.Element 타입입니다
<Component name="bar">
  <h1>Hello World</h1>
  <h2>Hello World</h2>
</Component>

// 오류: 자식은 JSX.Element의 배열 또는 문자열이 아닌 JSX.Element 타입입니다
<Component name="baz">
  <h1>Hello</h1>
  World
</Component>

JSX Result Type

By default, the result of a JSX expression is any Type.
JSX.Element You can change it to that type through the interface.
However, information about elements, properties, or children within JSX cannot be retrieved through that interface.
The interface is a black box.

To Include an Expression

JSX uses braces to express expressions between tags ({ }) to put it in.

var a = (
  <div>
    {["foo", "bar"].map((i) => (
      <span>{i / 2}</span>
    ))}
  </div>
);

The above code can't diverge a number through a string, so you'll get an error as a result.
preserve The output using the options is as follows:

var a = (
  <div>
    {["foo", "bar"].map(function (i) {
      return <span>{i / 2}</span>;
    })}
  </div>
);

React Integration

To use React and JSX together React typingmust be used.
This typing is appropriate for use with React. JSX Define a namespace.

/// <reference path="react.d.ts" />

interface Props {
  foo: string;
}

class MyComponent extends React.Component<Props, {}> {
  render() {
    return <span>{this.props.foo}</span>;
  }
}

<MyComponent foo="bar" />; // 성공
<MyComponent foo={0} />; // 오류

JSX Configuration

There are various compiler flags used for JSX customization, which act as compiler flags and inline file-specific pragma. More details can be learned through the tsconfig reference page:

Translation of Iterators and Generators.md

title: Iterators and Generators
layout: docs
permalink: /ko/docs/handbook/iterators-and-generators.html
oneline: How Iterators and Generators work in TypeScript

translatable: true

Iterable

Symbol.iterator Objects that have an implementation for a property are considered iterables.
Array, Map, Set, String, Int32Array, Uint32ArrayBuilt-in types such as , , etc. Symbol.iterator The property is already implemented.
In an object Symbol.iterator The function returns a list of values to iterate.

for..of The door

for..ofStatements inside an object Symbol.iterator Call the property to iterate over the iterable object.
Here's a simple array for..of The loop is:

let someArray = [1, "string", false];

for (let entry of someArray) {
  console.log(entry); // 1, "string", false
}

for..of vs. for..inThe door

for..ofand for..inThe statements all iterate through the list, but the values that they repeat are different. for..inis the object that repeats rudder Returns a list, but for..ofis the numeric property of the repeating object. value Returns a list.

The following is an example of this difference:

let list = [4, 5, 6];

for (let i in list) {
  console.log(i); // "0", "1", "2",
}

for (let i of list) {
  console.log(i); // "4", "5", "6"
}

Another difference is that for..inIt's just that it works on all these objects. So I use it as a way to check the properties of an object.
On the other hand for..offocuses primarily on the values of iterable objects. Mapand Set The same built-in object can access the stored value. Symbol.iterator Implement the properties.

let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";

for (let pet in pets) {
  console.log(pet); // "species"
}

for (let pet of pets) {
  console.log(pet); // "Cat", "Dog", "Hamster"
}

Code Generation

ES5 and ES3 Targeting

If you are targeting an ES5 or ES3-compatible engine, the iterator is Array It accepts only type values.
Symbol.iterator Even if you implement a property, you can still use it in a non-Array value. for..of Using a loop will result in an error.

The compiler is for..ofSimple about for Create a loop, for example:

let numbers = [1, 2, 3];
for (let num of numbers) {
  console.log(num);
}

The compiler generates the above code as follows:

var numbers = [1, 2, 3];
for (var _i = 0; _i < numbers.length; _i++) {
  var num = numbers[_i];
  console.log(num);
}

ECMAScript 2015 and higher version targeting

If you are targeting an ECMAScipt 2015-compliant engine, the compiler will target the built-in iterator implementation in the engine. for..of Create a loop.

Translation of Decorators.md

title: Decorators
layout: docs
permalink: /ko/docs/handbook/decorators.html
oneline: TypeScript Decorators overview

translatable: true

Introduction

Further Reading:
A Complete Guide to TypeScript Decorators

With the introduction of classes in TypeScript and ES6, there are certain scenarios that require additional functionality to annotate or modify classes and their members.
Decorators provide a way to add annotations and meta-programming syntax to class declarations and members.
Decorator for JavaScript Step 2 Proposalis available as an experimental feature of TypeScript.

consultation  Decorators are an experimental feature that may change in a future release.

To enable experimental support for decorators, use the command line or tsconfig.jsonIn experimentDecorators You need to enable the compiler options:

Command Line:

tsc --target ES5 --experimentalDecorators

tsconfig.json:

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true
  }
}

Decorators

_Decorator_The Class Declaration, method, accessor, Properties or parameterA special kind of declaration that can be attached to .
The decorator is @expression Use the format. Here expressionmust be a function that is called at run time with information about the decorated declaration.

For example, decorators @sealedUsing as follows sealed You can write a function.

function sealed(target) {
    // 'target' 변수와 함께 무언가를 수행합니다.
}

Decorator Factories

If you want to change the way decorators are applied to declarations, you can create a decorator factory. _Decorator Factory_is simply a function that returns an expression that the decorator will call at run time.

You can create a decorator factory in the following ways:

function color(value: string) { // 데코레이터 팩토리
    return function (target) { // 데코레이터
        // 'target'과 'value' 변수를 가지고 무언가를 수행합니다.
  };
}

Decorator Composition

You can apply multiple decorators to a declaration, as shown in the following example:

  • For a single row:
// @experimentalDecorators
// @noErrors
function f() {}
function g() {}
// ---cut---
@f @g x
  • For multiple rows:
// @experimentalDecorators
// @noErrors
function f() {}
function g() {}
// ---cut---
@f
@g
x

If multiple decorators are applied to a single declaration, Synthetic functions in mathematicsSimilar to .
Functions in this model _f_and _g_When synthesizing (f_∘_g)(x) The result of the synthesis of ) f(g(x)).

So when using multiple decorators in a single declaration in TypeScript, the following steps are taken:

  1. The representation of each decorator is evaluated from top to bottom.
  2. The result is then called as a function from the bottom up.

Decorator FactoryIf you use , you can observe this sequence of performances with the following example:

// @experimentalDecorators
function first() {
  console.log("first(): factory evaluated");
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("first(): called");
  };
}

function second() {
  console.log("second(): factory evaluated");
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("second(): called");
  };
}

class ExampleClass {
  @first()
  @second()
  method() {}
}

This outputs the result to the console.

first(): factory evaluated
second(): factory evaluated
second(): called
first(): called

Decorator Evaluation

How to apply decorators to various declarations in a class is well defined as follows:

  1. method, accessor or _Property Decorator_followed by _Parameter Decorator_applies to each instance member.
  2. method, accessor or _Property Decorator_followed by _Parameter Decorator_applies to each static member.
  3. _Parameter Decorator_applies to the constructor.
  4. _Class Decorator_applies to the class.

Class Decorators

Class Decoratoris declared just before the class is declared.
Class decorators are applied to the class constructor and can be used to observe, modify, or replace class definitions.
Class decorators are used in declaration files or other surrounding contexts, such as 선언 class).

The expression of the class decorator is called as a function at run time with the constructor of the decorated class as the only argument.

When the class decorator returns a value, replace it with a constructor function where the class provides a declaration.

consultation  If you choose to return a new constructor function, you must maintain the original prototype.
The logic of applying decorators at run time is to make this feature It doesn't do it for you.

Here's how to BugReport The class decorator applied to the class (@sealed) is an example.

// @experimentalDecorators
function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}
// ---cut---
@sealed
class BugReport {
  type = "report";
  title: string;

  constructor(t: string) {
    this.title = t;
  }
}

Using the following function declaration: @sealed You can define decorators.

function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealedWhen runs, it wraps both the constructor and the prototype.

Here's an example of how to override the constructor:

// @errors: 2339
// @experimentalDecorators
function reportableClassDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
  return class extends constructor {
    reportingURL = "http://www...";
  };
}

@reportableClassDecorator
class BugReport {
  type = "report";
  title: string;

  constructor(t: string) {
    this.title = t;
  }
}

const bug = new BugReport("Needs dark mode");
console.log(bug.title); // Prints "Needs dark mode"
console.log(bug.type); // Prints "report"

// Note that the decorator *does not* change the TypeScript type
// and so the new property `reportingURL` is not known
// to the type system:
bug.reportingURL;

Method Decorators

_Method Decorator_is declared just before the method is declared.
The decorator is the method of Property Descriptor and can be used to observe, modify, or replace method definitions.
Method decorators can be used in declaration files, overloads, or other surrounding contexts, such as 선언 class).

The expression of the method decorator is called as a function at run time with the following three arguments:

  1. The constructor function of the class for a static member, or a prototype of the class for an instance member.
  2. Name of the member
  3. Member's Property Descriptor

consultation  The script target is lower than 'ES5' Property Descriptor becomes 'undefined'.

If the method decorator returns a value, the method's Property Descriptor Used as:

consultation  If the script target is lower than 'ES5', the return value is ignored.

Here's how to Greeter A method decorator applied to a method in a class (@enumerable) is an example:

// @experimentalDecorators
function enumerable(value: boolean) {
  return function (target: any,propertyKey: string,descriptor: PropertyDescriptor) {
    descriptor.enumerable = value;
  };
}
// ---cut---
class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }

  @enumerable(false)
  greet() {
    return "Hello, " + this.greeting;
  }
}

Using the following function declaration: @enumerable You can define decorators.

function enumerable(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.enumerable = value;
  };
}

@enumerable(false)The decorator is Decorator FactoryIs.
@enumerable(false) When the decorator is called, the property descriptor enumerable Modify the properties.

Accessor Decorators

_Accessor decorator_is declared just before the accessor declaration.
The accessor decorator is the accessor's _Property Descriptor_and can be used to observe, modify, or replace the definition of an accessor.
An accessor decorator is used in a declaration file or in another peripheral context, such as 선언 class).

consultation  TypeScript for a single member get and set Unable to decorate accessors.
Instead, all decorators of the member should be applied to the first accessor specified in document order.
Because, decorators are not individual declarations. getand set Combining Accessors _Property Descriptor_This is because it applies to .

The expression of the accessor decorator is called as a function at run time with the following three arguments:

  1. A constructor function of a class for a static member or a prototype of a class for an instance member
  2. Name of the member
  3. Member's Property Descriptor

consultation  The script target is lower than 'ES5' _Property Descriptor_The undefinedwill be.

If the accessor decorator returns a value, the member's _Property Descriptor_Used as:

consultation  If the script target is lower than 'ES5', the return value is ignored.

Here's how to Point Accessor decorators applied to members of a class (@configurable) is an example:

// @experimentalDecorators
function configurable(value: boolean) {
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    descriptor.configurable = value;
  };
}
// ---cut---
class Point {
  private _x: number;
  private _y: number;
  constructor(x: number, y: number) {
    this._x = x;
    this._y = y;
  }

  @configurable(false)
  get x() {
    return this._x;
  }

  @configurable(false)
  get y() {
    return this._y;
  }
}

Using the following function declaration: @configurable You can define decorators:

function configurable(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.configurable = value;
  };
}

Property Decorators

_Property Decorator_is declared just before the property declaration.
Property decorators can be used in declaration files or other surrounding contexts, such as 선언 class).

The expression of the property decorator is called as a function at run time with the following two arguments:

  1. A constructor function of a class for a static member or a prototype of a class for an instance member
  2. Name of the member

consultation  In TypeScript 프로퍼티 데코레이터Due to the way is initialized. _Property Descriptor_is not provided as an argument to the property decorator.
This is because when defining the members of the current prototype, there is no mechanism to describe the instance properties, and there is no way to observe or modify the initializers of the properties. The return value is also ignored.
Therefore, a property decorator can only be used to observe that a property with a particular name has been declared to a class.

You can use this information to record metadata about a property, as in the following example:

class Greeter {
  @format("Hello, %s")
  greeting: string;

  constructor(message: string) {
    this.greeting = message;
  }

  greet() {
    let formatString = getFormat(this, "greeting");
    return formatString.replace("%s", this.greeting);
  }
}

Using the following function declaration: @format Decorators and getFormat You can define a function:

import "reflect-metadata";

const formatMetadataKey = Symbol("format");

function format(formatString: string) {
  return Reflect.metadata(formatMetadataKey, formatString);
}

function getFormat(target: any, propertyKey: string) {
  return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}

@format("Hello, %s") The decorator is Decorator FactoryIs.
@format("Hello, %s")When is called reflect-metadata Library's Reflect.metadata Use a function to add a metadata entry for a property.
getFormatWhen called, it reads the metadata value of the type.

consultation  In this example, reflect-metadata A library is required.
reflect-metadata For more information about the library, see MetadataSee .

Parameter Decorators

_Parameter Decorator_is declared immediately before the parameter is declared.
The parameter decorator is applied to a function in the class constructor or method declaration.
Parameter decorators can be used in declaration files, overloads, or other peripheral contexts, such as 선언 class).

The expression of the parameter decorator is called as a function at runtime with the following three arguments:

  1. A constructor function of a class for a static member or a prototype of a class for an instance member
  2. Name of the member
  3. Ordinal index of a parameter in the function's parameter list

consultation  A parameter decorator can be used to observe a parameter only when it is declared in a method.

The return value of the mezzanine decorator is ignored.

Here's how to BugReport Parameter decorator (@required) is an example:

// @experimentalDecorators
function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<any>) {}
function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {}
// ---cut---
class BugReport {
  type = "report";
  title: string;

  constructor(t: string) {
    this.title = t;
  }

  @validate
  print(@required verbose: boolean) {
    if (verbose) {
      return this.title;
    } else {
      return `type: ${this.type}\ntitle: ${this.title}`;
    }
  }
}

Using the following function declaration: @required and @validate You can define decorators.

// @errors: 2339 2339 2339
// @experimentalDecorators
// @emitDecoratorMetadata
import "reflect-metadata";
const requiredMetadataKey = Symbol("required");

function required(target: Object, propertyKey: string | symbol, parameterIndex: number) {
  let existingRequiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || [];
  existingRequiredParameters.push(parameterIndex);
  Reflect.defineMetadata( requiredMetadataKey, existingRequiredParameters, target, propertyKey);
}

function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
  let method = descriptor.value!;

  descriptor.value = function () {
    let requiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyName);
    if (requiredParameters) {
      for (let parameterIndex of requiredParameters) {
        if (parameterIndex >= arguments.length || arguments[parameterIndex] === undefined) {
          throw new Error("Missing required argument.");
        }
      }
    }
    return method.apply(this, arguments);
  };
}

@required The decorator adds metadata entries that display the parameters as needed.
And then @validate A decorator is a function that validates arguments before calling the original method, which is existing greet Wrap the method.

consultation  In this example, reflect-metadata A library is required.
reflect-metadata For more information about the library, see [Metadata] See (#메타데이터-metadata).

Metadata

Some examples are Experimental metadata APIAdd a polyfill for reflect-metadata Use a library.
This library is not yet part of the ECMAScript (JavaScript) standard.
However, when decorators are officially adopted as part of the ECMAScript standard, these extensions will be adopted.

You can install it via npm.

npm i reflect-metadata --save

TypeScript includes experimental support for emitting metadata of a specific type for declarations with decorators.
To enable this experimental support, use the command line ortsconfig.jsonIn emitDecoratorMetadata You must set compiler options.

command line:

tsc --target ES5 --experimentalDecorators --emitDecoratorMetadata

tsconfig.json:

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Once activated, reflect-metadataSimply import the library and additional design-time type information is available at run time.

You can see this in the following example:

// @errors: 2339
// @emitDecoratorMetadata
// @experimentalDecorators
// @strictPropertyInitialization: false
import "reflect-metadata";

class Point {
  constructor(public x: number, public y: number) {}
}

class Line {
  private _start: Point;
  private _end: Point;

  @validate
  set start(value: Point) {
    this._start = value;
  }

  get start() {
    return this._start;
  }

  @validate
  set end(value: Point) {
    this._end = value;
  }

  get end() {
    return this._end;
  }
}

function validate<T>(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<T>) {
  let set = descriptor.set!;
  
  descriptor.set = function (value: T) {
    let type = Reflect.getMetadata("design:type", target, propertyKey);

    if (!(value instanceof type)) {
      throw new TypeError(`Invalid type, got ${typeof value} not ${type.name}.`);
    }

    set.call(this, value);
  };
}

const line = new Line()
line.start = new Point(0, 0)

// @ts-ignore
// line.end = {}

// Fails at runtime with:
// > Invalid type, got object not Point

The TypeScript compiler is @Reflect.metadata Use decorators to inject design-time type information.
You can think of it as the same as the following TypeScript:

class Line {
  private _start: Point;
  private _end: Point;

  @validate
  @Reflect.metadata("design:type", Point)
  set start(value: Point) {
    this._start = value;
  }
  get start() {
    return this._start;
  }

  @validate
  @Reflect.metadata("design:type", Point)
  set end(value: Point) {
    this._end = value;
  }
  get end() {
    return this._end;
  }
}

consultation  Decorator metadata is an experimental feature and may have major changes in future releases.

Translation of Declaration Merging.md

title: Declaration Merging
layout: docs
permalink: /ko/docs/handbook/declaration-merging.html
oneline: How merging namespaces and interfaces works

translatable: true

Introduction

Some of the unique concepts of TypeScript describe the shape of JavaScript objects at the type level.
A special example of TypeScript is the concept of 'merging declarations'.
Once you understand this concept, you will have many benefits when working with traditional JavaScript.
It will also open the door to advanced abstraction concepts.

To get back to the point, "merge declarations" means that the compiler combines two separate declarations declared with the same name into one definition.
This merged definition has the characteristics of both declarations in its original form. You can merge any number of declarations to be merged;
It does not restrict you to merging only two declarations.

Basic Concepts

In TypeScript, a declaration generates at least one entity in 3 groups of namespaces, types, or values.
Namespace-generated declarations use dot notation to generate a namespace with a name to access.
A type-generation declaration generates a type that is bound to a given name and expressed in the declared form.
Finally, the value-generation declaration produces output that you can see in JavaScript.

Declaration Type Namespace type value
Namespace X X
class X X
Enumeration X X
interface X
Type aliases X
function X
variable X

Understanding the results produced by each declaration helps you understand the merged output when you merge declarations.

Merging Interfaces

The simplest and most common type of declarative merge is interface merge.
At the most basic level, merging mechanically combines the members of two declarations into a single interface of the same name.

interface Box {
  height: number;
  width: number;
}

interface Box {
  scale: number;
}

let box: Box = { height: 5, width: 6, scale: 10 };

Non-function members of an interface must be unique.
If they are not unique, they must all be of the same type.
If an interface declares a function member of the same name, but with a different type, the compiler will throw an error.

For function members, each function member with the same name is treated as overloading of the same function.
It is also important to note that if you merge interface A with a later interface, the second interface will have a higher priority than the first.

For example:

interface Cloner {
  clone(animal: Animal): Animal;
}

interface Cloner {
  clone(animal: Sheep): Sheep;
}

interface Cloner {
  clone(animal: Dog): Dog;
  clone(animal: Cat): Cat;
}

The above three interfaces can be merged into a single declaration as follows:

interface Cloner {
  clone(animal: Dog): Dog;
  clone(animal: Cat): Cat;
  clone(animal: Sheep): Sheep;
  clone(animal: Animal): Animal;
}

Note that the elements in each group are in the same order, but the group itself will be placed in the first place as it is overloaded later.

There is an exception to this rule called specialized signatures.
What if unity If there is a parameter that is of type string literal (for example, if the string literal is not a union), the signature will be raised to the top of the merged overload list.

For example, the following interfaces are merged:

interface Document {
  createElement(tagName: any): Element;
}
interface Document {
  createElement(tagName: "div"): HTMLDivElement;
  createElement(tagName: "span"): HTMLSpanElement;
}
interface Document {
  createElement(tagName: string): HTMLElement;
  createElement(tagName: "canvas"): HTMLCanvasElement;
}

DocumentThe result of the merged declaration of is as follows:

interface Document {
  createElement(tagName: "canvas"): HTMLCanvasElement;
  createElement(tagName: "div"): HTMLDivElement;
  createElement(tagName: "span"): HTMLSpanElement;
  createElement(tagName: string): HTMLElement;
  createElement(tagName: any): Element;
}

Merging Namespaces

Like an interface, a namespace with the same name merges with a namespace member.
Because a namespace creates both a namespace and a value, you need to understand how the two merge.

To merge namespaces, type definitions are merged from the exported interfaces declared in each namespace, forming a single namespace with merged interface definitions inside.

To merge namespace values, the namespace value is expanded by adding the exported members of the second namespace to the first to the existing namespace, if there is already a namespace with the specified name in each declaration location.

These are examples: Animals Merge Declaration of:

namespace Animals {
  export class Zebra {}
}

namespace Animals {
  export interface Legged {
    numberOfLegs: number;
  }
  export class Dog {}
}

These include:

namespace Animals {
  export interface Legged {
    numberOfLegs: number;
  }

  export class Zebra {}
  export class Dog {}
}

This model of namespace merging is a good starting point, but we need to understand what happens to unexported members.
Members that are not exported can only be viewed in the original namespace (the unmerged namespace). This means that after the merge, members merged into a different declaration will not be able to see the unexported members.

This is made more clear in the example below:

namespace Animal {
  let haveMuscles = true;

  export function animalsHaveMuscles() {
    return haveMuscles;
  }
}

namespace Animal {
  export function doAnimalsHaveMuscles() {
    return haveMuscles; // 오류, haveMuscles가 여기에 접근할 수 없기 때문에
  }
}

haveMuscles is not exported, so it shares the same unmerged namespace animalsHaveMuscles Only functions can see this symbol.
doAnimalsHaveMuscles functions, merged Animal Even if you are a member of a namespace, you cannot see members that have not been exported.

Merging Namespaces with Classes, Functions, and Enums

Namespaces are flexible enough to merge with declarations of other types.
To do this, the namespace declaration must follow the declaration to be merged. The resulting declaration has properties of both declaration types.
TypeScript uses this to model patterns in JavaScript and other programming languages.

Merging Namespaces with Classes

This part refers to how to describe the inner classes.

class Album {
  label: Album.AlbumLabel;
}
namespace Album {
  export class AlbumLabel {}
}

The visibility rules for merged members are: Merging Namespaces As described in the session, AlbumLabelYou must export the class before you can see the merged class.
The end result is a class that is managed within another class.
You can also use namespaces to add more static members to an existing class.

In addition to the inner class pattern, you'll also be familiar with extending functions by creating them in JavaScript and adding properties.
TypeScript securely preserves and can be defined by merging declarations.

function buildLabel(name: string): string {
  return buildLabel.prefix + name + buildLabel.suffix;
}

namespace buildLabel {
  export let suffix = "";
  export let prefix = "Hello, ";
}

console.log(buildLabel("Sam Smith"));

Similarly, the namespace can extend the enumeration of static members:

enum Color {
  red = 1,
  green = 2,
  blue = 4,
}

namespace Color {
  export function mixColor(colorName: string) {
    if (colorName == "yellow") {
      return Color.red + Color.green;
    } else if (colorName == "white") {
      return Color.red + Color.green + Color.blue;
    } else if (colorName == "magenta") {
      return Color.red + Color.blue;
    } else if (colorName == "cyan") {
      return Color.green + Color.blue;
    }
  }
}

Disallowed Merges

Not all merging is allowed in TypeScript.
Classes cannot be merged with other classes or variables.
For information about replacing merging classes, see Mixins in TypeScript You can see it in the section.

Module Augmentation

JavaScript does not support merging modules, but it can be patched by importing and updating existing objects.
Let's look at an easy observable example:

// observable.ts
export class Observable<T> {
  // ... 연습을 위해 남겨둠 ...
}

// map.ts
import { Observable } from "./observable";
Observable.prototype.map = function (f) {
  // ... 연습을 위해 남겨둠
};

This works fine in TypeScript, but the compiler Observable.prototype.mapI don't know about .
Module enrichment allows you to tell the compiler information:

// observable.ts
export class Observable<T> {
  // ... 연습을 위해 남겨둠 ...
}

// map.ts
import { Observable } from "./observable";
declare module "./observable" {
  interface Observable<T> {
    map<U>(f: (x: T) => U): Observable<U>;
  }
}
Observable.prototype.map = function (f) {
  // ... 연습을 위해 남겨둠
};

// consumer.ts
import { Observable } from "./observable";
import "./map";
let o: Observable<number>;
o.map((x) => x.toFixed());

The module name is import/exportis interpreted in the same way as the module specifier in .
For more information, see moduleSee .
The enriched declarations are then merged as if they were declared in the same file as the original.

However, keep in mind two limitations:

  1. You can't make a new top-level declaration to an enrichment -- you can only patch an existing declaration.
  2. Default exports cannot be enriched, only exports with a name (must be extended by that name, defaultis a reserved word - for more information #14080)

Global augmentation

Inside the module, you can add declarations to the global scope:

// observable.ts
export class Observable<T> {
  // ... 연습을 위해 남겨둠 ...
}

declare global {
  interface Array<T> {
    toObservable(): Observable<T>;
  }
}

Array.prototype.toObservable = function () {
  // ...
};

Global reinforcement has the same behavior and limitations as module reinforcement.

Translation of Integrating with Build Tools.md

title: Integrating with Build Tools
layout: docs
permalink: /ko/docs/handbook/integrating-with-build-tools.html

oneline: How to use TypeScript with other build tools

Build Tools

Babel

installation

npm install @babel/cli @babel/core @babel/preset-typescript --save-dev

.babelrc

{
  "presets": ["@babel/preset-typescript"]
}

Using the Command Line Interface

./node_modules/.bin/babel --out-file bundle.js src/index.ts

package.json

{
  "scripts": {
    "build": "babel --out-file bundle.js main.ts"
  },
}

Using the Command Line Interface

npm run build

Browserify

installation

npm install tsify

Using the Command Line Interface

browserify main.ts -p [ tsify --noImplicitAny ] > bundle.js

Using the API

var browserify = require("browserify");
var tsify = require("tsify");

browserify()
    .add("main.ts")
    .plugin("tsify", { noImplicitAny: true })
    .bundle()
    .pipe(process.stdout);

For more information: smrq/tsify

Duo

installation

npm install duo-typescript

Using the Command Line Interface

duo --use duo-typescript entry.ts

Using the API

var Duo = require("duo");
var fs = require("fs")
var path = require("path")
var typescript = require("duo-typescript");

var out = path.join(__dirname, "output.js")

Duo(__dirname)
    .entry("entry.ts")
    .use(typescript())
    .run(function (err, results) {
        if (err) throw err;
        // 컴파일된 결과를 출력 파일에 작성합니다
        fs.writeFileSync(out, results.code);
    });

For more information: frankwallis/duo-typescript

Grunt

installation

npm install grunt-ts

default gruntfile.js

module.exports = function(grunt) {
    grunt.initConfig({
        ts: {
            default : {
                src: ["**/*.ts", "!node_modules/**/*.ts"]
            }
        }
    });
    grunt.loadNpmTasks("grunt-ts");
    grunt.registerTask("default", ["ts"]);
};

For more information: TypeStrong/grunt-ts

Gulp

installation

npm install gulp-typescript

default gulpfile.js

var gulp = require("gulp");
var ts = require("gulp-typescript");

gulp.task("default", function () {
    var tsResult = gulp.src("src/*.ts")
        .pipe(ts({
              noImplicitAny: true,
              out: "output.js"
        }));
    return tsResult.js.pipe(gulp.dest("built/local"));
});

For more information: ivogabe/gulp-typescript

Jspm

installation

npm install -g jspm@beta

Note: Currently, jspm's TypeScript support is 0.16beta.

For more information: TypeScriptSamples/jspm

Webpack

installation

npm install ts-loader --save-dev

The default webpack.config when using Webpack 2 .js

module.exports = {
    entry: "./src/index.tsx",
    output: {
        path: '/',
        filename: "bundle.js"
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js", ".json"]
    },
    module: {
        rules: [
            // '.ts' 또는 '.tsx' 확장자를 가진 모든 파일은 'ts-loader'에 의해 처리됩니다.
            { test: /\.tsx?$/, use: ["ts-loader"], exclude: /node_modules/ }
        ]
    }
}

The default webpack.config when using Webpack 1 .js

module.exports = {
    entry: "./src/index.tsx",
    output: {
        filename: "bundle.js"
    },
    resolve: {
        // '.ts'와 '.tsx'를 해석 가능한 확장자로 추가합니다.
        extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },
    module: {
        loaders: [
            // '.ts' 또는 '.tsx' 확장자를 가진 모든 파일은 'ts-loader'에 의해 처리됩니다.
            { test: /\.tsx?$/, loader: "ts-loader" }
        ]
    }
}

More about ts-loaderSee here.

Fall back:

MSBuild

Locally installed Microsoft.TypeScript.Default.props (top) and Microsoft.TypeScript.targets Update the project file to include the (bottom) file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- 하단에 default props 포함 -->
  <Import
      Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props"
      Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.Default.props')" />

  <!-- TypeScript 환경 설정 -->
  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
    <TypeScriptRemoveComments>false</TypeScriptRemoveComments>
    <TypeScriptSourceMap>true</TypeScriptSourceMap>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release'">
    <TypeScriptRemoveComments>true</TypeScriptRemoveComments>
    <TypeScriptSourceMap>false</TypeScriptSourceMap>
  </PropertyGroup>

  <!-- 하단에 default targets 포함 -->
  <Import
      Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets"
      Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets')" />
</Project>

For more information about MSBuild compiler option definitions: Setting compiler options for MSBuild projects

NuGet

  • > Manage NuGet Packages
  • Microsoft.TypeScript.MSBuildSearch for
  • Install Click
  • Once installed, rebuild it!

For more information, see Package Manager Dialogand Using NuGet and nightly buildsSee also

Translation of Configuring Watch.md

title: Configuring Watch
layout: docs
permalink: /ko/docs/handbook/configuring-watch.html
oneline: How to configure the watch mode of TypeScript

translatable: true

On how the compiler will monitor files and directories

  • TypeScript 3.8+: Compiler flags
  • Earlier version: Environment variables
    to set it up.

Background

Compiler's --watch The implementation is provided by node fs.watchand fs.watchFileRelies on , both of which have their pros and cons.

fs.watchuses file system events to notify you of changes to the file/directory. However, it depends on the OS, the notifications are completely unbelievable, and they don't work as expected on many OSes. In addition, there may be a limit to the number of watchers that can be created (for example, linux), and programs with a large number of files can be used up very quickly. However, because this operation uses file system events, it does not involve much CPU cycle. Compilers are usually fs.watchto monitor the directory. (e.g. the source directory contained in the config file, the directory where the module verification failed... etc.) to handle the missing precision in notifications about changes. However, the recursive watchdog feature is only supported on Windows and OSX. In other words, other OSes need something to replace the recursive attribute.

fs.watchFileuses polling, so it includes CPU cycles. However, this is the most reliable mechanism to receive updates on file/directory status. Compilers are usually fs.watchFileto monitor source files, configuration files, and missing files (see Missing files), which means that CPU usage depends on the number of files in the program.

Configuring file watching using a tsconfig.json

{
  // Some typical compiler options
  "compilerOptions": {
    "target": "es2020",
    "moduleResolution": "node"
    // ...
  },

  // NEW: Options for file/directory watching
  "watchOptions": {
    // Use native file system events for files and directories
    "watchFile": "useFsEvents",
    "watchDirectory": "useFsEvents",

    // Poll files for updates more frequently
    // when they're updated a lot.
    "fallbackPolling": "dynamicPriority"
  }
}

You can read more about this in the release notes.

Environment Variables TSC*WATCHFILEConfiguring file watching using environment variable TSC*WATCHFILE)

options explanation
PriorityPollingInterval fs.watchFile, but uses different polling intervals for source files, config files, and missing files.
DynamicPriorityPolling Use dynamic queues that poll frequently for files that are modified frequently, and poll unchanged files less frequently.
UseFsEvents Using file system events fs.watchto be notified of file changes/creation/deletions. (fs.watchmay work differently for different OSes.) For example. Linux has a limit on the number of watchers and fs.watchIf you fail to create a watcher using , fs.watchFileYou will use to create a watcher.
UseFsEventsWithFallbackDynamicPolling This option is fs.watchIf you fail to create a watcher using , except that polling is done via a dynamic queue. UseFsEvents It's similar to an option. (The thing about dynamic queues is DynamicPriorityPollingDescribed in Options.).
UseFsEventsOnParentDirectory This option is fs.watchWatches the parent directory of the file (using file system events). However, CPU usage may increase and accuracy may decrease.
default (no value specified) Environment VariablesTSC*NONPOLLING*WATCHERIf set to true, watches the parent directory of the file. (UseFsEventsOnParentDirectorySame as ).false fs.watchFileUse the 250ms It monitors all files with a time limit.

Environment VariablesTSC*WATCHDIRECTORYConfiguring directory watching using environment variable TSC*WATCHDIRECTORY)

On platforms that do not natively support recursive witness of directories on node, the directory witness feature is TSC*WATCHDIRECTORYis supported by recursively creating a directory watcher for a subdirectory using the various options selected in . By default, on platforms that support recursive directory supervision (such as windows), the value of this environment variable is ignored.

options explanation
RecursiveDirectoryUsingFsWatchFile fs.watchFileto watch for directories and subdirectories that are polling watches (with CPU cycles).
RecursiveDirectoryUsingDynamicPriorityPolling Use a dynamic polling queue to poll for changes to directories and subdirectories.
default (no value specified) fs.watchto watch for directories and subdirectories.
Translation of Understanding Errors.md

title: Understanding Errors
layout: docs
permalink: /ko/docs/handbook/2/understanding-errors.html

oneline: "How to see errors in TypeScript."

Understanding Errors

When TypeScript finds an error, it tries to explain in as much detail as possible what went wrong.
Because TypeScript's type system is structural, it can provide a detailed description of where the problem was found.

Terminology

Knowing the terms that often appear in error messages will help you understand them.

Assign (assignable to)

TypeScript is a type that can be replaced by another type when it can be replaced by another type. Can be assigned It is expressed as is.
In other words, 고양이The 동물Because it can replace 동물to Can be assigned You.

As the name suggests, this relationship is tand sBy examining the type of t = s;Used to determine the validity of the assignment of
It is also used when checking in most places where the two types interact.
For example, when you call a function, the type of each argument is the type declared as a parameter. Can be assigned Must have.

Informally T is not assignable to SIf you say TypeScript, "_Tand Sis not compatible"_You just have to think that you are saying:
However, this is not the case Directional Keep in mind that this is a relationship: Sprice TJust because it can be assigned to Tprice SIt cannot be assigned to .

Examples

Let's take a look at some examples of error messages and see what is happening.

Error Elaborations

Each error starts with a leading message and sometimes leads to more submessages.
You can think of each submessage as answering the "why?" question about the message above.
Let's take a look at how it actually works with a few examples.

The following example generates an error message that is longer than the example itself:

// @errors: 2322
let a: { m: number[] }
let b = { m: [""] }
a = b

On the last line, TypeScript found an error.
The logic for the error comes from the logic of checking that the assignment is healthy:

  1. b The type is a Can it be assigned to a type? No. Why?
  2. because m This is because the types of attributes are not compatible. Why?
  3. because bof m Attribute (string[]) is aof m Attribute (number[]) cannot be assigned. Why?
  4. The type of an array of elements (string) to another type (number) cannot be assigned.

Extra Properties

// @errors: 2322
type A = { m: number }
const a: A = { m: 10, n: "" }

Union Assignments

// @errors: 2322
type Thing = "none" | { name: string }

const a: Thing = { name: 0 }
Translation of Conditional Types.md

title: Conditional Types
layout: docs
permalink: /ko/docs/handbook/2/conditional-types.html

oneline: "Creating a type that behaves like an if statement in the type system."

The key to most useful programs is that the output must be determined by the input.
JavaScript programs aren't much different, but given the fact that you can easily check the type of a value, the decision on the output is also based on the type of input.
Conditional Type can help explain the relationship between input and output types.

interface Animal {
  live(): void;
}
interface Dog extends Animal {
  woof(): void;
}

type Example1 = Dog extends Animal ? number : string;
//   ^?

type Example2 = RegExp extends Animal ? number : string;
//   ^?

Conditional types are the ternary operator conditional statements in JavaScript (condition ? trueExpression : falseExpression) has the same shape.

type SomeType = any;
type OtherType = any;
type TrueType = any;
type FalseType = any;
type Stuff =
  // ---cut---
  SomeType extends OtherType ? TrueType : FalseType;

extendsBased on , if the type on the left can be assigned to the right type, you get the first branch (the "true" value branch), otherwise you get the subsequent branch (the "false" value branch).

Dog extends Animal Follow on numberI stringAside from telling you if it's cognitive, in the example above, conditional types don't seem very useful!
But when used in conjunction with generics, conditional types have powerful forces.

For example, the following createLabel Let's look at a function.

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}

function createLabel(id: number): IdLabel;
function createLabel(name: string): NameLabel;
function createLabel(nameOrId: string | number): IdLabel | NameLabel;
function createLabel(nameOrId: string | number): IdLabel | NameLabel {
  throw "unimplemented";
}

The overloads of createLabel represent a single JavaScript function based on the input type. Note the following:

  1. If the library has to create a similar kind of function throughout the API every time, it becomes cumbersome.
  2. We have 3 overloads, i.e. for each case positive Have a type (or each numberand string) and the general case (string | number) should have. createLabelTo deal with new types of , the number of overloads increases exponentially.

Instead, you can encode logic as a conditional type.

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}
// ---cut---
type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;

Using conditional types allows you to simplify up to a single function without overloading.

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}
type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;
// ---cut---
function createLabel<T extends number | string>(idOrName: T): NameOrId<T> {
  throw "unimplemented";
}

let a = createLabel("typescript");
//  ^?

let b = createLabel(2.8);
//  ^?

let c = createLabel(Math.random() ? "hello" : 42);
//  ^?

Limiting to conditional types

Often, new information can be obtained from a conditional type of inspection.
Just as Type Guard narrows it down to more specific types, branching of the "true" value of conditional types can further limit generics depending on the type you are contrasting.

Consider the following example:

// @errors: 2536
type MessageOf<T> = T["message"];

In the example above, Tprice message I don't know if I have a property, so I'm getting an error in TypeScript.
TYou can limit the type of to make TypeScript no longer make errors.

type MessageOf<T extends { message: unknown }> = T["message"];

interface Email {
  message: string;
}

type EmailMessageContents = MessageOf<Email>;
//   ^?

but MessageOf can receive any type, message If there are no properties, never Can I make it determined by type?
Here it is possible by moving the constraint to the outside and applying conditional types.

type MessageOf<T> = T extends { message: unknown } ? T["message"] : never;

interface Email {
  message: string;
}

interface Dog {
  bark(): void;
}

type EmailMessageContents = MessageOf<Email>;
//   ^?

type DogMessageContents = MessageOf<Dog>;
//   ^?

Within the "true" value branch, TypeScript is Tprice message Have Properties to be You can tell.

In another example, if it is an array type, it will flatten it to the individual element types of the array, but if it is not an array type, it will remain the same. Flatten You can create a type.

type Flatten<T> = T extends any[] ? T[number] : T;

// Extracts out the element type.
type Str = Flatten<string[]>;
//   ^?

// Leaves the type alone.
type Num = Flatten<number>;
//   ^?

FlattenGiven an array type, numberThrough index access using string[]You can get the element type of .
Otherwise, it returns the given type.

Infering within conditional types

We've seen above that you can extract a type using a conditional type with constraints.
This is a mundane task that makes conditional types easier.

The conditional type is infer You can use keywords to deduce the types you are comparing from the "true" value branch.
For example FlattenYou can infer the element type without extracting it "directly" from to the indexed access type.

type Flatten<Type> = Type extends Array<infer Item> ? Item : Type;

Here in the "true" value branch TWithout having to present the element type of , infer Keywords for New Generic Type Variables ItemI used it declaratively in .
This approach avoids the need to deeply analyze the structure of the type of person you are interested in.

infer You can use keywords to use useful helper type aliases.
For example, let's look at a simple case for extracting a return type from a function type.

type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
  ? Return
  : never;

type Num = GetReturnType<() => number>;
//   ^?

type Str = GetReturnType<(x: string) => string>;
//   ^?

type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>;
//   ^?

When inferring a type with multiple call signatures (like an overlot function type), last You'll deduce by the signature (perhaps, which is acceptable in all cases). You can't handle overloads based on a list of argument types.

declare function stringOrNum(x: string): number;
declare function stringOrNum(x: number): string;
declare function stringOrNum(x: string | number): string | number;

type T1 = ReturnType<typeof stringOrNum>;
//   ^?

Decentralized conditional type

On top of a generic type, a conditional type encounters a union type, Decentralised It works.
For example, let's look at the following:

type ToArray<Type> = Type extends any ? Type[] : never;

ToArrayIf you pass a union type to , the conditional type is applied to each member of the union.

type ToArray<Type> = Type extends any ? Type[] : never;

type StrArrOrNumArr = ToArray<string | number>;
//   ^?

StrArrOrNumArrHere's how this works:

type StrArrOrNumArr =
  // ---cut---
  string | number;

Each member type of a union maps efficiently.

type ToArray<Type> = Type extends any ? Type[] : never;
type StrArrOrNumArr =
  // ---cut---
  ToArray<string> | ToArray<number>;

And I get the result as follows:

type StrArrOrNumArr =
  // ---cut---
  string[] | number[];

In general, dispersion is the desired behavior. To avoid this behavior: extendsJust wrap the sides of the keyword in brackets.

type ToArrayNonDist<Type> = [Type] extends [any] ? Type[] : never;

// 'StrArrOrNumArr' is no longer a union.
type StrArrOrNumArr = ToArrayNonDist<string | number>;
//   ^?
Translation of Everyday Types.md

title: Everyday Types
layout: docs
permalink: /ko/docs/handbook/2/everyday-types.html

oneline: "Primitive types of languages."

This chapter covers the most common types found in JavaScript code and explains how they are described in TypeScript and their respective counterparts.
We're not going to cover all of them in this article, and we'll cover more ways to create and use types in the chapters that follow.

Types are much more than just type notation _location_may appear in
In addition to learning about the type itself, we will also learn about the cases in which you refer to a type when you want to create a new struct.

Let's start by revisiting some of the most basic and common types you might encounter when writing JavaScript or TypeScript code.
These types are the key components that make up the more complex types that we will discuss later.

Raw Type: string, numberand boolean

Three very common uses in JavaScript Primitive Typeto string, numberand booleanThere is.
Each of these types has a corresponding type in TypeScript.
As you might expect, these types are used in JavaScript to match the value for each type. typeof It has the same name that you get when you use the operator.

  • stringsilver "Hello, world"indicates a string value such as
  • numbersilver 42Represents a number such as . JavaScript does not have a separate runtime value for integers, so int or floatThere is no such thing as . All the numbers are simply numberIs
  • booleansilver trueand falsehas only two values

String, Number, BooleanTypes such as (starting with uppercase letters) are valid types, but it is extremely rare to use such a special built-in type in your code. All the time string, number, boolean Use a type.

array

[1, 2, 3]When specifying the type of an array, such as number[] You can use syntax. This syntax can be used by any type (for example, string[]is an array of strings).
The above type is Array<number>It can be written in the same form as , and has the same meaning.
T<U> For information about syntax, see Generic Let's find out more when dealing with .

[number]has a completely different meaning. Tuple Type See section.

any

TypeScript is also any, and can be used when you don't want a type checking error to occur because of a certain value.

What type of value is anyIf so, any attribute can be accessed for that value (and the type of value returned is also any), can be called as if it were a function, assign (receive), or do anything else that is syntactically valid.

let obj: any = { x: 0 };
// 아래 이어지는 코드들은 모두 오류 없이 정상적으로 실행됩니다.
// `any`를 사용하면 추가적인 타입 검사가 비활성화되며,
// 당신이 TypeScript보다 상황을 더 잘 이해하고 있다고 가정합니다.
obj.foo();
obj();
obj.bar = 100;
obj = "hello";
const n: number = obj;

any Types can be useful when you don't want to redefine a long type just because of just one purpose of reassuring TypeScript that there is nothing wrong with a particular line in your code.

noImplicitAny

If TypeScript cannot deduce that type from the context for an untyped value, the compiler will any Giving a type is the default behavior.

However, this situation is usually not preferred. because anyis because type checking is not done.
Compiler Flags noImplicitAnyUsing implicitly anyThrows an error in all cases that you consider to be

Type notation for variables

const, varor let When declaring a variable using the like, you can add type notation to explicitly specify the type of the variable, which is optional.

let myName: string = "Alice";
//        ^^^^^^^^ 타입 표기

TypeScript is int x = 0;Do not use the notation of the expression "type to the left", as in .
Type notation is always the object of the type. On the back Location.

However, in most cases, type notation is not necessary.
If possible, TypeScript automatically uses the types in the code to _inference_Try to do it.
For example, the type of a variable is inferred based on the type of the supervalue of that variable.

// 타입 표기가 필요하지 않습니다. 'myName'은 'string' 타입으로 추론됩니다.
let myName = "Alice";

In most cases, you don't need to explicitly learn the rules of reasoning.
If you're just getting started with TypeScript, try using as little type notation as possible. You'll be surprised to learn that you don't need a lot of types to fully understand the flow of code.

function

Functions are the primary means of sending and receiving data in JavaScript.
TypeScript allows you to specify the input and output types of functions.

Parameter Type Notation

When you declare a function, you can specify the type after each parameter to declare the type of parameters that the function will allow.
The parameter type is written after the parameter name.

// 매개변수 타입 표기
function greet(name: string) {
  //                 ^^^^^^^^
  console.log("Hello, " + name.toUpperCase() + "!!");
}

If the parameter indicates a type, the arguments to that function are checked.

// @errors: 2345
declare function greet(name: string): void;
// ---셍략---
// 만약 실행되면 런타임 오류가 발생하게 됩니다!
greet(42);

Even if you don't specify the type in the parameter, TypeScript still checks whether the correct number of arguments are passed.

Return Type Notation

The return type can also be indicated.
The return type is written after the parameter list.

function getFavoriteNumber(): number {
  //                        ^^^^^^^^
  return 26;
}

As with the type notation of a variable, it is common to not have to specify the return type. Because TypeScript is contained in that function. return This is because we will infer the return type based on the statement.
The type notation used in the example above doesn't mean much.
Sometimes there is code that performs explicit typing for documentation purposes, to prevent incorrect modifications to the code, or out of a very personal preference.

Anonymous functions

Anonymous functions are a bit different from function declarations.
If you can figure out how a function will be called by looking where it is in your code, TypeScript automatically assigns a type to the function's parameters.

Below is an example.

Here's an example:

// @errors: 2551
// 아래 코드에는 타입 표기가 전혀 없지만, TypeScript는 버그를 감지할 수 있습니다.
const names = ["Alice", "Bob", "Eve"];

// 함수에 대한 문맥적 타입 부여
names.forEach(function (s) {
  console.log(s.toUppercase());
});

// 화살표 함수에도 문맥적 타입 부여는 적용됩니다
names.forEach((s) => {
  console.log(s.toUppercase());
});

parameter sDespite the fact that the type is not specified in , TypeScript is sWith the deduced type of array to find out the type of forEach We used the type of the function.

The process is _Give contextual types_because the function is executed _context_to know what type the function should have.
Similar to the rules of reasoning, you don't have to explicitly learn how this process works, but if this is the case, _What actually happens_This will help you distinguish between cases where type notation is unnecessary.
Examples of how the context in which a value occurs affects the type of that value will be explored later.

Object Type

Except for primitive types, the types encountered the most are _Object Type_Is.
An object is a JavaScript value that has properties, which is the case in most cases!
To define an object type, simply list the properties of the object and the types of each property.

For example, the function below is taking an object that appears to be coordinates as an argument.

// 매개 변수의 타입은 객체로 표기되고 있습니다.
function printCoord(pt: { x: number; y: number }) {
  //                      ^^^^^^^^^^^^^^^^^^^^^^^^
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 3, y: 7 });

The parameters above are xand yis denoted as a type of two properties, both of which are number Type.
When you distinguish between each property , or ;, and the notation of the last delimiter is optional.

The type notation of each property is also optional.
If you do not specify a type, the property is any Consider it a type.

Optional Properties

An object type is a type of some or all of the properties that is optional, that is, _Optional_can be specified as:
Property name followed by ?You can add .

function printName(obj: { first: string; last?: string }) {
  // ...
}
// 둘 다 OK
printName({ first: "Bob" });
printName({ first: "Alice", last: "Alisson" });

In JavaScript, when you access a property that doesn't exist, you don't get a run-time error. undefined You get a value.
Because of this, the Optional Properties Read When, prior to using that value undefinedYou need to check whether it is or not.

// @errors: 2532
function printName(obj: { first: string; last?: string }) {
  // 오류 - `obj.last`의 값이 제공되지 않는다면 프로그램이 멈추게 됩니다!
  console.log(obj.last.toUpperCase());
  if (obj.last !== undefined) {
    // OK
    console.log(obj.last.toUpperCase());
  }

  // 최신 JavaScript 문법을 사용하였을 때 또 다른 안전한 코드
  console.log(obj.last?.toUpperCase());
}

Union Type

TypeScript's type system allows you to create new types using a variety of operators based on existing types.
Now that you know how to use some types, you can use them In combination It's time to try it out in an interesting way.

To Define Union Types

The first way to combine types is to Union It's about using types.
A union type is created using two or more different types, and the value of a union type is one of the types used for type combinations. _Anything One_can be had as a type.
Each type used in the combination is a union type _member_Call.

Let's write a function that can receive a string or a number.

// @errors: 2345
function printId(id: number | string) {
  console.log("Your ID is: " + id);
}
// OK
printId(101);
// OK
printId("202");
// 오류
printId({ myID: 22342 });

Using Union Types

Values that match the union type Provided by It's that simple. You can provide a type that corresponds to one of the members of the union type.
A value that is of type Union is in the code When it exists, how do I use it?

When dealing with a union in TypeScript, the union type all Allowed only when the operation is valid for a member.
For example string | numberFor a union type named string You cannot use methods that are only valid for types.

// @errors: 2339
function printId(id: number | string) {
  console.log(id.toUpperCase());
}

To solve this, use Union in your code Narrow This is the same as what happens in JavaScript without type notation.
_Narrow_An issue occurs when TypeScript can infer a value to a more specific type based on the code structure.

For example, TypeScript is only string Value only typeof As the result of the operation "string"I know you can have .

function printId(id: number | string) {
  if (typeof id === "string") {
    // 이 분기에서 id는 'string' 타입을 가집니다

    console.log(id.toUpperCase());
  } else {
    // 여기에서 id는 'number' 타입을 가집니다
    console.log(id);
  }
}

Another example is Array.isArrayis to use a function like .

function welcomePeople(x: string[] | string) {
  if (Array.isArray(x)) {
    // 여기에서 'x'는 'string[]' 타입입니다
    console.log("Hello, " + x.join(" and "));
  } else {
    // 여기에서 'x'는 'string' 타입입니다
    console.log("Welcome lone traveler " + x);
  }
}

else Please note that branch statements do not need to be processed separately. xThe type of string[]If not, xThe type of must be stringIt will be.

Sometimes all members of a union may have something in common.
For example, arrays and strings are both slice Embedding methods.
If all members of a union have a property in common, they can use it without narrowing it.

// 반환 타입은 'number[] | string'으로 추론됩니다
function getFirstThree(x: number[] | string) {
  return x.slice(0, 3);
}

Union is semantically union, which actually means that the Union type is the property of _intersection_It seems to point to and can feel confusing.
This is no coincidence. _Union_The name comes from type theory.
number | string Union Types have their own types About the values It is constructed by taking a union.
Given two sets and attributes for each set, the two sets of _Union_There are a number of characteristics of each _intersection_Please note that only applies.
For example, let's say you have tall people wearing hats in one room and people in the other room who speak Spanish. If you combine the two rooms, all What we can know about people is that everyone must wear a hat.

Type aliases

Until now, when using object types and union types, they were written directly.
This is convenient, but there are times when you want to reuse the same type more than once or call it by another name.

_Type aliases_exists for this very case, _type_for _name_to provide.
The syntax of the type alias is as follows:

type Point = {
  x: number;
  y: number;
};

// 앞서 사용한 예제와 동일한 코드입니다
function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}

printCoord({ x: 100, y: 100 });

Type aliases allow you to give new names to any type, not just object types.
For example, you can also give a type alias to a union type as shown below.

type ID = number | string;

The type alias is merely Please note that it is nothing more than an alias. In other words, using type aliases does not create "multiple versions" that are distinct from each other for the same type.
To use an alias is to create a new separately named type.
In other words, the code below looks like it's wrong. Can be seen However, this is normal in TypeScript because each type is an alias for the same type.

declare function getInput(): string;
declare function sanitize(str: string): string;
// ---cut---
type UserInputSanitizedString = string;

function sanitizeInput(str: string): UserInputSanitizedString {
  return sanitize(str);
}

// 보안 처리를 마친 입력을 생성
let userInput = sanitizeInput(getInput());

// 물론 새로운 문자열을 다시 대입할 수도 있습니다
userInput = "new input";

interface

_Interface Declaration_is another way to create object types.

interface Point {
  x: number;
  y: number;
}

function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}

printCoord({ x: 100, y: 100 });

As with the use of type aliases, the example code above behaves as if it were using an arbitrary anonymous object with no type.
TypeScript is only printCoordof the value passed to _rescue_I'm only interested. In other words, it only depends on whether you have the predicted properties.
As such, the fact that we are only interested in the structure and capabilities of a type means that TypeScript Structured That's why it's called a type system.

Differences between type aliases and interfaces

The interface is very similar to the type alias, and in most cases you are free to choose between the two to use.
interfaceMost of the functions that it has are typeThe same is available in . The most important difference between the two is that types cannot be opened to add new properties, whereas interfaces can always be extended.

인터페이스 타입

인터페이스 확장하기

interface Animal {
  name: string
}
interface Bear extends Animal { honey: boolean }
const bear = getBear() bear.name bear.honey

교집합을 통하여 타입 확장하기

type Animal = {
  name: string
}
type Bear = Animal & { honey: Boolean }
const bear = getBear(); bear.name; bear.honey;

기존의 인터페이스에 새 필드를 추가하기

interface Window {
  title: string
}
interface Window { ts: TypeScriptAPI }
const src = 'const a = "Hello World"'; window.ts.transpileModule(src, {});

타입은 생성된 뒤에는 달라질 수 없다

type Window = {
  title: string
}
type Window = { ts: TypeScriptAPI }
// Error: Duplicate identifier 'Window'.

The above concepts will be taught in more detail in the following chapters, so don't worry if you don't understand them well now.

In most cases, you can choose between interface and type according to your personal preferences, and TypeScript will suggest a different choice if necessary. If you're not sure, first of all interfaceWhen using and subsequently experiencing problems. typePlease use the

Type affirmation

Sometimes there are cases where you know more information about the type of any value than TypeScript.

For example, in code document.getElementByIdIf is used, TypeScript is used at this time. HTMLElement During _something_While you can only see that is returned, you can always use the ID used on the page. HTMLCanvasElementYou may already know that is returned.

In this case, _Type affirmation_allows you to be more specific about the type.

const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

As with type notation, type affirmations are removed by the compiler and do not affect the run-time behavior of your code.

The use of angle brackets is also a way to use (the code .tsx if it is not a file) and it has the same meaning.

const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");

Remember: Type assertions are removed at compile time, so checks related to type assertions are not made during runtime.
Even if the type affirmation is incorrect, an exception is thrown, or nullThis will not be created.

In TypeScript, More specific or Less specific Only type affirmations that convert to version types are allowed.
These rules prevent the following "impossible" coercion:

// @errors: 2352
const x = "hello" as number;

This rule is sometimes overly conservative, disallowing coercion that can be complex but valid.
In this case, you can use two assertions. any(or as we will introduce later) unknown), and then to the type you want.

declare const expr: any;
type T = { a: 1; b: 2; c: 3 };
// ---cut---
const a = (expr as any) as T;

Literal Type

stringand numberIn addition to common types such as, Specific You can specify string and numeric values in the type position.

To understand this, think of the different methods provided for variable declarations in JavaScript. varand let You can change the kind of value that can be stored in both variables. constThis is not possible. These features are reflected in the way TypeScript generates types for literal values.

let changingString = "Hello World";
changingString = "Olá Mundo";
// 변수 `changingString`은 어떤 문자열이든 모두 나타낼 수 있으며,
// 이는 TypeScript의 타입 시스템에서 문자열 타입 변수를 다루는 방식과 동일합니다.
changingString;
// ^?

const constantString = "Hello World";
// 변수 `constantString`은 오직 단 한 종류의 문자열만 나타낼 수 있으며,
// 이는 리터럴 타입의 표현 방식입니다.
constantString;
// ^?

Literal types are not very significant in themselves.

// @errors: 2322
let x: "hello" = "hello";
// OK
x = "hello";
// ...
x = "howdy";

A variable that can only have one value is useless!

But literals with Union When used together, you will be able to express more useful concepts. For example, you might define a function that can accept only certain kinds of values as arguments.

// @errors: 2345
function printText(s: string, alignment: "left" | "right" | "center") {
  // ...
}
printText("Hello, world", "left");
printText("G'day, mate", "centre");

Numeric literal types can also be used in the same way.

function compare(a: string, b: string): -1 | 0 | 1 {
  return a === b ? 0 : a > b ? 1 : -1;
}

Of course, it can also be used with non-literal types.

// @errors: 2345
interface Options {
  width: number;
}
function configure(x: Options | "auto") {
  // ...
}
configure({ width: 100 });
configure("auto");
configure("automatic");

There is another literal type. That's the bull literal type.
There are only two types of bull literals, which, as you might expect, trueand falseIs.
boolean The type itself is in fact just true | false An alias of type Union.

Literal inference

When you initialize a variable with an object, TypeScript assumes that the object's properties may subsequently change its value.
For example, let's say you write code like this:

declare const someCondition: boolean;
// ---cut---
const obj = { counter: 0 };
if (someCondition) {
  obj.counter = 1;
}

Existing Value 0In the field that was 1When you assign , TypeScript does not consider it an error.
To put it another way: obj.counterBe sure to number Must have a type, 0 It means you can't have a literal type. Because the type is Read and writing This is because it is used to determine both behaviors.

The same applies to strings.

// @errors: 2345
declare function handleRequest(url: string, method: "GET" | "POST"): void;
// ---cut---
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);

In the example above, req.methodThe stringNot deduced as, "GET"is not deduced as. reqThe timing of its creation and handleRequestCode evaluation can occur any amount of time between the invocation points of , at which point req.methodat "GUESS"Because a new string such as may be assigned, TypeScript determines that there is an error in the above code.

There are two ways to resolve these cases:

  1. You can change the way you reason by adding type affirmations in either location.

    declare function handleRequest(url: string, method: "GET" | "POST"): void;
    // ---cut---
    // 수정 1:
    const req = { url: "https://example.com", method: "GET" as "GET" };
    // 수정 2
    handleRequest(req.url, req.method as "GET");

    Revision 1 is req.methodThere is always Literal Type "GET"It intends to win, and accordingly in the corresponding field "GUESS"We will prevent the assignment of a value such as " in the first place".
    Revision 2 states that "For some reason, req.methodprice "GET"knows that you have a value."

  2. as constYou can use to convert an entire object to a literal type.

    declare function handleRequest(url: string, method: "GET" | "POST"): void;
    // ---cut---
    const req = { url: "https://example.com", method: "GET" } as const;
    handleRequest(req.url, req.method);

as const Suffixes are common constworks similarly to , for all properties of that object. string or numberEnsures that values of literal types rather than more general types such as are assigned.

nulland undefined

There are two primitive values in JavaScript that point to empty or uninitialized values. straight nulland undefinedIs.

TypeScript has two names with the same name corresponding to each value. _type_This exists. The way each type works is strictNullChecks It depends on whether the option is set or not.

strictNullChecksWhen is not set

strictNullChecksprice If it's not set, what value is null or undefinedEven if it could, you can access that value as usual, nulland undefinedcan be assigned to any type of variable.
This is similar to how languages that do not do null checking (C#, Java, etc.) behave.
The lack of null checking is also a major cause of bugs. For no apparent reason, throughout the code strictNullChecks It is always recommended that you set the options.

strictNullChecks When set up

strictNullChecksprice If it is set, what value is null or undefinedWhen , you should test that value before you use a method or property with that value.
Before using optional properties undefined As with checking whether or not _Narrow_Through nullYou can perform a check on any value that can be.

function doSomething(x: string | undefined) {
  if (x === undefined) {
    // 아무 것도 하지 않는다
  } else {
    console.log("Hello, " + x.toUpperCase());
  }
}

Non-null assertion operator (suffix !)

In TypeScript, the type is set up without explicit checking. nulland undefinedProvides a special syntax to remove .
After the expression !When you create , its value is null or undefinedis to affirm that it is not type.

function liveDangerously(x?: number | undefined) {
  // 오류 없음
  console.log(x!.toFixed());
}

Like other type assertions, this syntax does not change the run-time behavior of the code, so ! The operator must have that value null or undefinedprice Is not It should only be used.

Enumeration

An enumeration is a feature that TypeScript adds to JavaScript, where any value is _A set of constants with names_The ability to restrict it to one of the values that belong to . Unlike most TypeScript features, this feature has a type level in JavaScript. Is not, a feature that is added at the language and runtime level. So you probably need to know what an enum is, but if you don't have a clear idea of how to use it, it's a good idea to put it on hold for actual use. To learn more about enumerations Enumeration documentsPlease read on.

Primitive types that are not often used

In addition to the aforementioned types, we will cover the rest of the JavaScript primitive types that exist in the type system.
Of course, I'm not going to go into depth here.

bigint

Since ES2020, primitive types have been added to JavaScript to handle very large integers. straight bigintIs.

// @target: es2020

// BigInt 함수를 통하여 bigint 값을 생성
const oneHundred: bigint = BigInt(100);

// 리터럴 구문을 통하여 bigint 값을 생성
const anotherHundred: bigint = 100n;

For more information about BigInt, see TypeScript 3.2 Release NotesYou can check it out here.

symbol

symbolis a primitive type that can be used to generate globally unique reference values. Symbol() You can create it through a function.

// @errors: 2367
const firstName = Symbol("name");
const secondName = Symbol("name");

if (firstName === secondName) {
  // 절대로 일어날 수 없습니다
}

For more information about Symbol, see Symbol DocumentsYou can check it out here.

Translation of Basics.md

title: The Basics
layout: docs
permalink: /ko/docs/handbook/2/basic-types.html
oneline: "The first step in learning TypeScript: Basic types."
preamble: >

Welcome to the first chapter of the Handbook, and if you're new to TypeScript, you're welcome to the ''Get StartedI recommend reading one of the guide documents first.

Every value in JavaScript has its own set of different actions, which can be verified by executing various operations.
This may sound a bit abstract, as a simple example. messageLet's take a look at some of the operations that you can perform on a variable named .

// 'message'의 프로퍼티 'toLowerCase'에 접근한 뒤
// 이를 호출합니다
message.toLowerCase();

// 'message'를 호출합니다
message();

Analyzing the above code, first of all, the first line of executable code is toLowerCaseaccesses the property and calls it.
On the second line, messageYou are trying to call directly.

but messageIf you don't know what the value of is—in general, it is—I can't say for sure what the result of the execution of the above code will be.
The behavior of each operation is completely dependent on what value you had in the first place.

  • messageis callable?
  • toLowerCaseDo you have a property called ?
  • If you have, toLowerCase Is it also callable?
  • If both values are callable, what does each return?

These are common questions that we struggle with when writing code in JavaScript, and we always hope that we don't miss every detail about them.

messageLet's say is defined as below.

const message = "Hello World!";

As you might have guessed, here message.toLowerCase()If we run , we will get a value where the same string consists of only lowercase letters.

So what about the second line of code we saw earlier?
If you're familiar with JavaScript, you know it won't run with exceptions.

TypeError: message is not a function

It would be great if we could prevent mistakes like this in advance.

The JavaScript runtime uses the value of the value to determine what it should do when the code is executed. type, that is, to see what actions and abilities the value has.
This is what it is TypeErrorimplies that. In the example above, the string is "Hello World"is saying that cannot be called as a function.

Some values, such as stringand numberFor values of primitive types such as , typeof Operators allow you to know the type of each value at the time of execution.
However, for other values, such as function values, there is no mechanism at which the type of that value is executed, as in the aforementioned manner.
For example, consider the following function:

function fn(x) {
  return x.flip();
}

Looking at the above code, the object passed as an argument is a callable property. flipOnly by reading the code that the above function will work well if we have You can tell. But JavaScript doesn't know what we know about this information while the code is running.
In pure JavaScript fnThe only way to know what is doing with a particular value is to call it and see what happens.
Behavior like this makes it difficult to predict before the code runs. In other words, it's hard to know while you're writing the code what the behavior results will be.

In this respect, _type_What value is Iran fnA concept that can be passed to , and which explains that any value will fail to execute.
JavaScript is only Dynamic You only provide types, and you have to run the code to see what happens.

The alternative to this is Static Executing code using the type system ago It's about making predictions about your code.

Static type checking

Seen stringObtained when you wanted to call as a function. TypeErrorLet's return to the story of .
Most people I don't want to see any errors when I run the code. It is considered a bug!
And when we write new code, we do our best not to create new bugs.

Here, if you add a little code, save the file, and then immediately notice the error when you run the code again, you can quickly isolate the problem. But that's not always the case.
If you haven't tested the feature enough, you may not be able to spot any potential errors!
Or, even if you're lucky enough to find an error, you may end up going through a sizable refactoring and unintentionally digging deep into your code as you add new code.

Ideally, to run the code ago It would be great if you had a tool that could detect these bugs in advance.
That's what a static type checker like TypeScript does.
_Static type system_describes the form and behavior of the values used in the programs we have written.
Type checkers like TypeScript take advantage of this information to let us know when a program isn't working properly.

// @errors: 2349
const message = "hello!";

message();

If you run the last example above with TypeScript, you'll first check for error messages before the code runs.

Non-exception execution failure

So far, we've covered runtime errors. This is the case if the JavaScript runtime tells us directly that something is strange.
These errors can be attributed to how JavaScript should respond when an unexpected problem occurs. ECMAScript SpecificationThis is because you provide an explicit procedure in .

For example, according to the specification, an error occurs if you attempt to make a call to something that is not callable.
This may sound like a "natural move", but someone might think that they should also throw an error when they try to access a property that doesn't exist in the object.
But instead, JavaScript reacts quite differently. undefinedReturns the .

const user = {
  name: "Daniel",
  age: 26,
};

user.location; // undefined 를 반환

Ultimately, a static type system should let you know if any code is "valid" JavaScript code that does not cause an error, if it is considered an error within the static type system.
In TypeScript, the code below is locationThis will raise an error that it is not defined.

// @errors: 2339
const user = {
  name: "Daniel",
  age: 26,
};

user.location;

Although sometimes this will cost you flexibility in expression, the purpose of doing so is not an explicit bug, but rather to catch cases that are reasonably considered bugs.
And TypeScript has these seemingly invisible bugs. Pretty much Grab it.

For example, typos,

// @noErrors
const announcement = "Hello World!";

// 바로 보자마자 오타인지 아실 수 있나요?
announcement.toLocaleLowercase();
announcement.toLocalLowerCase();

// 아마 아래와 같이 적으려 했던 것이겠죠...
announcement.toLocaleLowerCase();

Uncalled functions,

// @noUnusedLocals
// @errors: 2365
function flipCoin() {
  // 본래 의도는 Math.random()
  return Math.random < 0.5;
}

Or a basic logic error, etc.

// @errors: 2367
const value = Math.random() < 0.5 ? "a" : "b";
if (value !== "a") {
  // ...
} else if (value === "b") {
  // 이런, 이 블록은 실행되지 않겠군요
}

Types as programming tools

TypeScript catches bugs when we make mistakes in our code.
That's good, but TypeScript is Going further from here, It prevents us from making mistakes the very moment we make them.

The Type Checker has relevant information so that we can check whether we are accessing the correct properties on a variable or other property.
Using this information, the Type Checker will show us which properties we can use. _proposition_You will be able to do it.

This means that TypeScript can be used to modify code, provide error messages as we type code, or provide code completion.
This is a common reference when discussing tools in TypeScript.

// @noErrors
// @esModuleInterop
import express from "express";
const app = express();

app.get("/", function (req, res) {
  res.sen
//       ^|
});

app.listen(3000);

TypeScript takes programming tools seriously, and this includes a lot more than just code completion and error message features.
Code editors that support TypeScript provide "Quick Fixes" that automatically fix errors, refactoring your code with ease, useful navigation to quickly jump to the definition of a variable, and searching for all references to a given variable.
All of these features are based on Type Checker and operate entirely cross-platform, Your favorite code editor supports TypeScriptThe probability of doing so is high.

tsc, TypeScript compiler

So far, we've talked about type checking, but it's still a type _Checker_I didn't use .
Our New Friends tscLet's say first hello to the TypeScript compiler.
First, let's install it using npm.

npm install -g typescript

If you run the above code, you will see the TypeScript compiler tscis installed globally.
tscLocal node_modules If you want to run it from a package npx Or you can use a similar tool.

Now go to the empty folder and click on the first TypeScript program, hello.tsLet's write .

// 세상을 맞이하세요.
console.log("Hello world!");

Note that no underscores are drawn in the code. This "hello world" program looks exactly like a "hello world" program written in JavaScript.
And now typescript Installed with the package tsc Run a command to perform type checking.

tsc hello.ts

Voila!

Wait, exactly _what_You mean you came out with this "voila"?
tscbut nothing happened!
Well, there was no type error, so nothing was going to be reported, so there was no output on the console.

But if we check again, we can see that instead of file I got the output.
Looking at the current directory, hello.ts Next to the file hello.js You can see that the file exists.
This tscOur hello.ts The file is a JavaScript file Compile or _metamorphosis_One deliverable.
And if you check that content, TypeScript will .ts After processing the file, you can see what it spit out.

// 세상을 맞이하세요.
console.log("Hello world!");

In the above case, TypeScript had very little to transform, so it yielded the same output that we wrote in the first place.
The compiler attempts to produce code that is as clean and readable as if it were written by a human.
Of course, it's not always easy, but TypeScript does the indentation consistently, takes into account that the code is written across multiple lines, and places the comments that are written around the code well.

If there is a type checking error Given What?
hello.tsLet's rewrite .

// @noErrors
// 아래는 실무 수준에서 범용적으로 쓰이는 환영 함수입니다
function greet(person, date) {
  console.log(`Hello ${person}, today is ${date}!`);
}

greet("Brendan");

Here tsc hello.tsKeep in mind that if you run again, you'll get an error on the command line!

Expected 2 arguments, but got 1.

TypeScript is greet You're telling me that I forgot to pass arguments to the function, and it really is.
So far, we've only written standard JavaScript, but we've still been able to spot problems in our code through type checking.
Thanks, TypeScript!

Throwing an error

I don't know if you noticed it in the example I looked at earlier, hello.js The contents of the file have been modified once again.
When you open the file, you'll see that it's practically the same as the code file used as input.
Look at our code tscmay seem a bit surprising given that has caused the error, but it's behavior based on one of the core values of TypeScript. That's right, in most cases You I think you know better than TypeScript.

As mentioned earlier, type checking for code restricts the actions that a program can execute. Therefore, there are some trade-offs and compromises in the range of behavior that type checking allows or restricts.
In most cases, the problem does not occur, but there are also scenarios where type checking is a hindrance.
For example, consider a case where you encounter a type checking error while migrating code written in JavaScript to TypeScript.
Eventually, we'll modify the code to make it pass type checking, but the truth is that the original JavaScript code was already working fine!
Is there a reason why the conversion to TypeScript should interrupt the execution of the code?

So TypeScript doesn't disturb you.
Of course, over time, you may want to be more defensive about mistakes and have TypeScript behave more rigorously.
In this case, --noEmitOnError You can do so by using the compiler option.
hello.ts After modifying the file, use the flag option above tscTry running .

tsc --noEmitOnError hello.ts

hello.jsYou can see that none of is modified.

Explicit types

So far it is still up to TypeScript person or datedidn't tell you what it was.
Modify the code so that TypeScript personTwo stringand dateprice Date Let them know it should be an object.
In addition dateof toDateString() Let's use the method.

function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

We just had personand dateas opposed to _Type notation_By doing the greetDescribed the types of values that can be used together when is called.
The signature is "greetThe string Type of personand Date Type of datehas a "have".

If there is one, TypeScript will be able to tell us if we have used the function incorrectly.
For example...

// @errors: 2345
function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

greet("Maddison", Date());

Yes?
TypeScript reported an error with respect to the second argument, so why?

Perhaps surprisingly, in JavaScript Date()When you call stringReturns the .
While new Date()Using Date You must create a type so that you can get back the results you originally expected.

Anyway, this error can be fixed very quickly.

function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

greet("Maddison", new Date());

Keep in mind that you don't always have to write explicit type notation.
In many cases, TypeScript provides omitted type information. Can be deduced (or "find out").

let msg = "hello there!";
//  ^?

msgprice string Even if you haven't told TypeScript that you have a type, TypeScript can figure it out.
This is a basic feature, and if the type system takes care of it and can somehow figure out the correct type, it's best not to write down the type notation.

Note: The speech balloon in the code immediately above is what appears on the mouse hover screen when you write the code in the editor.

Erased Type

Functions written earlier greet tscLet's see what happens when we compile it and get the JavaScript output.

// @showEmit
// @target: es5
function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}

greet("Maddison", new Date());

You can tell two things here:

  1. personand date Arguments no longer have type notation.
  2. "Template String" - Backtick (` Sentences written using the character - is a concatenation operator (+) converted to a regular string consisting of:

The second item will be discussed in more detail later, and the first item will be the first one.
Because type notation is not part of JavaScript (or strictly ECMAScript), there is currently no browser or runtime that can run TypeScript as-is without modification.
This is why when you want to use TypeScript, you need a compiler above all else. I need a way to remove or convert TypeScript-only code so that it can be executed.
Most TypeScript-only code is removed, and likewise, type notation is completely erased.

Remember: Type notation does not modify the runtime behavior of the program at all.

Downleveling

Another difference mentioned earlier, right below is the template string,

`Hello ${person}, today is ${date.toDateString()}!`;

It's been rewritten with the content below.

"Hello " + person + ", today is " + date.toDateString() + "!";

Why did this happen?

Template strings are ECMAScript 2015 (a.k.a. ECMAScript 6, ES2015, ES6, etc. Don't ask for more) is a feature that appeared in a version of ECMAScript.
TypeScript rewrites the code in a new version of ECMAScript into something older such as ECMAScript 3 or ECMAScript 5.
The process of replacing a new or "upper" version of ECMAScript with an old or "lower" version _Downleveling_It's also called .

The default behavior for TypeScript is to target a very older version of ECMAScript called ES3.
--target You can also set flags to convert a more recent version to a target.
--target es2015allows TypeScript to act as a target for ECMAScript 2015, which means that as long as ECMAScript 2015 is a supported runtime, the code will be converted to run.
consequently tsc --target es2015 input.tsand you will get the output as shown below.

function greet(person, date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
greet("Maddison", new Date());

The default for the target version is ES3, but the vast majority of browsers in existence support ES2015.
So if maintaining compatibility with a particular older browser isn't a major issue, in most cases you can rest assured that ES2015 or higher can be targeted by the compiler.

Severity

The purpose of using TypeScript's type checker varies from user to user.
Someone may want to maintain a loose level of performing type checking on only a portion of the program, while still taking full advantage of its functionality as a useful programming tool.
This is the experience you want to provide as a base when using TypeScript. Type checking is optional, type inference is based on the most generous criteria, and the potential null/undefined No checks are made on the values.
These basic experiences are made in a way that does not interfere with the development experience. In the event of the aforementioned error tscis similar to how handles errors.
If you're migrating from traditional JavaScript, this is a good level to take the first step.

In contrast, the majority of users prefer TypeScript to perform type checking to the fullest extent. This is also why TypeScript provides a strictness setting.
This severity setting makes a static type checker as if it were close to a dial from a switch-level device (which simply weighs whether code checking has been done or not).
The farther you turn the dial, the more TypeScript will examine you.
That will give you a little more work to do, but in the long run, it's definitely worth it, and you'll be able to use more thorough inspections and precise tool features.
If possible, you should always enable strictness in new code.

TypeScript has several type-checking strictness flags that you can turn on and off, and all future example code will be written with all flags enabled unless otherwise noted.
From the CLI --strict Set a flag or tsconfig.jsonat "strict": trueAdding will activate all flags at the same time. You can also turn off each flag individually.
The two main options you should know are noImplicitAnyand strictNullChecksIs.

noImplicitAny

In some cases, TypeScript does not deduce the type of the value, which is the most generous type. anyPlease remember that it is considered to be.
This is not the worst case. Anyway, type anyis also a matter of course in normal JavaScript.

but anyUsing often obscures the reason for using TypeScript in the first place.
The more specifically you use types in your program, the more validation and tooling features you can use, which means you'll encounter fewer bugs in your code.
noImplicitAny When you enable the flag, the type is anythrows an error for variables that are implicitly deduced from .

strictNullChecks

nulland undefinedThe default behavior is that values such as can be assigned to values of other types.
This makes it easy to code, but nulland undefinedForgetting the treatment of is the cause of the countless bugs in the world. Some people may find this A Million Dollar MistakeIt's also called!
strictNullChecks The flag is nulland undefinedto be more explicit, null and undefined Processing Forgot Whether or not you are having us in Liberate Gives.

Translation of TS for the New Programmer.md

title: TypeScript for the New Programmer
short: TS for the New Programmer
layout: docs
permalink: /ko/docs/handbook/typescript-from-scratch.html

oneline: Learn TypeScript from scratch

Congratulations on choosing TypeScript as your first language - a really good decision!

You've probably heard that Typescript is a "flavor" or "variant" of Javascript.
The relationship between TypeScript (TS) and JavaScript (JS) is quite unique in modern programming languages, so learning more about this relationship will help you learn how to add TypeScript to JavaScript.

A Short History of JavaScript (What is JavaScript? A Brief History)

JavaScript (also known as ECMAScript) was initially created as a scripting language for browsers.
JavaScript가 처음 나왔을 때, 수십 줄 이상의 코드를 작성하는 것은 다소 이례적인 일이었기에 웹 페이지� 속 짧은 코드들을 위해 사용할 것으로 여겨졌습니다.
Because of this, early web browsers took longer to execute more than a dozen lines of code.
However, as time went on and JS became more and more popular, web developers began to experience interactions using JS.

Web browser developers have optimized the execution engine (dynamic compilation) for the above increasing JS usage and extended what they can do with the optimized (adding APIs) to enable web developers to use more JS.
On modern websites, browsers frequently run applications that consist of hundreds of thousands of lines of code.
It starts with a simple network of static pages, and then goes all kinds of satisfying _Applications_It is a long and gradual growth of the "web" that has grown into a platform for .

In addition, JS has become famous enough to be used outside of the context of the browser, such as implementing JS servers using node.js.
The nature of JS, such as "works anywhere", makes it an attractive option for cross-platform development.
Today, many developers are only I'm programming the entire stack using only JavaScript!

In summary, we have JavaScript, the perfect tool designed for fast use and built to write millions of lines of applications.
Every language is its own Weird points - There are some weird and surprising things, and the proud but not proud beginnings of JavaScript are many You've created a problem. For example:

  • The same operator in JavaScript is (==a) argument By force conversion (coerces), causes unexpected behavior:

    if ("" == 0) {
      // 참입니다! 근데 왜죠??
    }
    if (1 < x < 3) {
      // *어떤* x 값이던 참입니다!
    }
  • JavaScript also allows access to properties that do not exist:

    const obj = { width: 10, height: 15 };
    // 왜 이게 NaN이죠? 철자가 어렵네요!
    const area = obj.width * obj.heigth;

Most programming languages will display errors when this kind of error occurs, and some will display them during compilation, before the code is executed.
When you're writing a small program, these weird things get upsetting, but you can manage them. But when writing hundreds or thousands of lines of applications, these constant surprises are a serious problem.

TypeScript: A Static Type Checker

We've said earlier that some languages don't run buggy programs at all.
Detecting errors in code without letting the program run _Static Checks_is called.
어떤 것이 오류인지와 어떤 것이 연산 되는 값에 기인하지 않음을 정하는 것�이 정적 type Inspection.

_Static Type Tester_TypeScript is a type before running the program _Types of values_Looks for errors in the program based on .
For example, the reason for the error in the last example above is objof type Because.
The following error you may see in TypeScript:

// @errors: 2551
const obj = { width: 10, height: 15 };
const area = obj.width * obj.heigth;

A Typed Superset of JavaScript

So what does TypeScript have to do with JavaScript?

Syntax

TypeScript is allowed the syntax of JS, JavaScript Supersets The language.
Syntax refers to how you write code to create a program.
For example, the following code )Because there is no syntax The error is:

// @errors: 1005
let a = (4

TypeScript doesn't see JavaScript code as an error because of its unique syntax.
That said, I don't know how it's written, but it works fine if I put the JavaScript code that works in a TypeScript file.

Types

However, TypeScript has added a way to use different kinds of values. Typed Superset.
gastric obj.heigth The error is syntax The type of value, not the error (type) is the result of the wrong use of ).

As another example, when the following JavaScript code is executed in a browser, the following value is output: will:

console.log(4 / []);

The above code, which is syntactically-legal, is in JavaScript. NaNOutputs the .
However, TypeScript determines that the operation of dividing a number into an array is not correct and throws an error:

// @errors: 2363
console.log(4 / []);

You can divide a number into an array with the intention of seeing what actually happens. But, most of them are programming mistakes.
TypeScript's Type Inspector is designed to help you create the right program while detecting as many common errors as possible.
(We'll look at the settings for how rigorously TypeScript can inspect your code later.)

If you move the code from the JavaScript file to the TypeScript code, depending on how you wrote the code, _Type Error_You can see it.
This could be a code problem, or TypeScript might be overly conservative.
To get rid of errors like the above, the guide will show you how to add various TypeScript syntax.

Runtime Behavior

TypeScript in JavaScript _Runtime characteristics_A programming language with
For example, in JavaScript, the act of dividing by 0 is not treated as a runtime exception and InfinityReturns a value.
Logically, TypeScript is the runtime attribute of JavaScript code never It doesn't change.

This means that even if TypeScript detects that there is a type error in the code, moving the JavaScript code to TypeScript will execute in the same way. Guaranteed

Maintaining the same runtime behavior as JavaScript is a fundamental commitment of TypeScript to make it easy to switch between the two languages without worrying about nuances that can break your program's behavior.

Erased Types

Roughly, when TypeScript's compiler finishes checking the code, the type is By deleting The result is "compiled" code.
This means that once the code is compiled, the resulting regular JS code has no type information.

The absence of type information is due to the type inferred by TypeScript in the program. _characteristic_It means that it doesn't change.
In conclusion, type errors may be displayed during compilation, but the type system itself has nothing to do with how the program works when it is run.

Finally, TypeScript does not provide an additional runtime library.
TypeScript allows programs to use the same standard library (or external library) as a JavaScript program, so you don't have to study TypeScript-related frameworks further.

Learning JavaScript and TypeScript

It's often asked, "Should I learn JavaScript or TypeScript?" You can see questions like

The correct answer is that you can't learn TypeScript without learning JavaScript!
TypeScript shares syntax and runtime attributes with JavaScript, so everything you learn in JavaScript will help you learn TypeScript at the same time.

There are many JavaScript learning resources for programmers; TypeScript를 작성�할 때 그런 학습 자원을 무시해선 Not.
For example javascriptTagged Questions typescriptAbout 20 times more than the tagged question, all javascriptThe question can also be applied to TypeScript.

If you're looking for something like "How to sort a list in TypeScript", remember: typescript is the runtime of javascript that has a compile-time type tester.
The way you sort a list in TypeScript can be done the same way in JavaScript.
That's great if you've found a resource that uses TypeScript directly, but you don't have to limit everyday questions to TypeScript-specific answers to run runtime tasks.


Here, I recommend learning a few JavaScript basics (JavaScript Guide in Mozilla Web DocsThat would be fine.)

Once you've gotten used to it, come back and TypeScript for JavaScript ProgrammersRead on, handbookStart or ExampleTake a look.

Translation of TS for OOPers.md

title: TypeScript for Java/C# Programmers
short: TS for Java/C# Programmers
layout: docs
permalink: /ko/docs/handbook/typescript-in-5-minutes-oop.html

oneline: Learn TypeScript if you have a background in object-oriented languages

TypeScript is a popular choice for programmers familiar with languages that use static typing, such as C# and Java.

TypeScript's type system offers many benefits of static typing, such as better code completion, early detection of errors, and clearer communication between parts of a program.
TypeScript offers a lot of these developer-friendly features, but we need to revisit how JavaScript (and TypeScript, too) differs from traditional object-oriented programming (OOP) languages.
Understanding these differences will help you write better JavaScript code and avoid the common pitfalls of programmers who are just getting started with TypeScript in C#/Java.

Learning JavaScript Together (Co-learning JavaScript)

If you're already familiar with JavaScript but are primarily a programmer using Java or C#, this introductory page can help explain common misconceptions and pitfalls.
Some of the ways the TypeScript model types are quite different from Java or C#, and it's important to keep this in mind when learning TypeScript.

If you are a Java or C# programmer new to JavaScript, you should first use types to understand the runtime behavior of JavaScript. Except It's a good idea to learn some of the parts of JavaScript.
TypeScript code Run Because it doesn't change the way you do it, you still have to learn how JavaScript works in order to write code that actually makes something work!

TypeScript is the same as JavaScript _Runtime_Because of the use of , it is very important to remember that resources that you want to implement certain runtime actions (converting strings to numbers, displaying warnings, writing files to disk, etc.) always apply equally well to your TypeScript program.
Don't limit yourself to only resources specific to TypeScript!

Rethinking the Class

C# and Java are Compulsory OOP It's called a language.
In these languages _class_is not only the basic unit of code configuration, but all data at runtime and It is the basic container for behavior.
Forcing all functions and data to be in a class can be a good domain model for some problems, but all domains will be represented in this way. _need_is not.

Free Functions and Data

In JavaScript, functions can be anywhere, and you are free to pass data without belonging to a predefined 'class' or 'struct'.
This flexibility is very powerful.
Regardless of the OOP layer, "free" (non-class-agnostic) functions that process data are preferred as a model for writing programs in JavaScript.

Static Classes

Additionally, certain structures, such as singletons and static classes in C# and Java, are not required in TypeScript.

OOP in TypeScript

This means that you can continue to use the class if you want!
Some problems are suitable for solving with the existing OOP layer, and TypeScript supports classes in JavaScript, making these models more effective.
TypeScript supports many common patterns, such as interfaces, inheritance, and static method implementations.

We'll cover classes later in this guide.

Rethinking Types

TypeScript _type_The understanding of is actually quite different from C# or Java.
Let's look at some of the differences.

Nominal Reified Type Systems

In C# and Java, a given value and object has exactly one type: null, primitive type, or defined class type.
To ask for the exact type at runtime point value.GetType() or value.getClass()You can call methods such as .
The definition of this type exists somewhere in the class with a specific name, and cannot be used interchangeably with each other, even if the two classes have similar shapes, unless there is an explicit inheritance or a commonly implemented interface.

This aspect is reified, nominal Describes the type system.
The types you use in your code exist at runtime, and types are associated through declarations, not structures.

Types as Sets

In C# or Java, the one-to-one correspondence between runtime types and their compile-time declarations is important.

In TypeScript, types share something in common _A set of values_It's better to think of:
Because a type is only a set, a particular value is at the same time numerous Can belong to a set.

Once you start thinking of types as sets, certain operations become very natural.
For example, in C#, 'string' and 'int' Both are possible Since the type does not exist, it is strange to pass this value as an argument.

The moment you realize in TypeScript that all types are simply sets, this becomes very natural.
How would you describe the values that can belong to the 'string' set or the 'number' set?
This value is simply the value of the sets of Union: ‘string | It belongs to number'.

TypeScript provides several ways to use types based on set theory, and it is more intuitive to think of types as sets.

Erased Structural Types

In TypeScript, an object is exactly a single type. No.
For example, when you create an object that satisfies an interface, you can use the object where that interface is expected, even if there is no declarative relationship between the two.

interface Pointlike {
  x: number;
  y: number;
}
interface Named {
  name: string;
}

function printPoint(point: Pointlike) {
  console.log("x = " + point.x + ", y = " + point.y);
}

function printName(x: Named) {
  console.log("Hello, " + x.name);
}

const obj = {
  x: 0,
  y: 0,
  name: "Origin",
};

printPoint(obj);
printName(obj);

TypeScript's type system is not nominal. _Structured_Is: objis a number xand y As you have properties, Pointlikecan be used as:
The relationship between types is determined by the properties they contain, not by whether they are declared as a particular relationship.

TypeScript's type system is also Not materialized: At runtime objprice PointlikeIt doesn't tell you.
In fact Pointlike The type is at run time In any form Does not exist.

Types as a set In terms of concepts, obj Pointlike A set of values or Named You can consider yourself a member of a set of values.

Consequences of Structural Typing

Object-oriented programmers are often surprised by two aspects of structured typing.

Empty Types

First _Empty Type_seems to ignore the expectation:

class Empty {}

function fn(arg: Empty) {
  // 무엇인가를 하나요?
}

// 오류는 없지만, '빈' 타입은 아니지 않나요?
fn({ k: 10 });

TypeScript is a given argument that is valid EmptyMake sure that it is fnchecks whether the call to is valid.
{ k: 10 }and class Empty { }Check the _structure of _ to validate it.
EmptySince there are no properties in Emptyto do all Properties { k: 10 }Belongs to:
Therefore, a valid call is:

Surprisingly, it is used very similarly to the final nominal object-oriented programming language.
Because the natural subtype relationship between the derived class and the base of the derived class is destroyed, the subclass is _delete_I can't.
The structural type system describes the subtype in terms of having the attributes of a compatible type, so it implicitly distinguishes the above relationship

Identical Types

Another frequent cause of surprise is due to the same type:

class Car {
  drive() {
    // hit the gas
  }
}
class Golfer {
  drive() {
    // hit the ball far
  }
}

// No error?
let w: Car = new Golfer();

Again, the reason why it is not an error is because of the class _rescue_is because they are the same.
This may be a reason for potential confusion, but it's not uncommon for classes that don't really matter to be the same.

We'll learn more about how classes relate to each other in a later class chapter.

Reflection

Object-oriented programmers are familiar with being able to handle any type of value, including generics.

// C#
static void PrintType<T>() {
    Console.WriteLine(typeof(T).Name);
}

Because TypeScript's type system has been completely cleared, information such as instantiation of generic type arguments is not available at runtime.

JavaScript has typeofand instanceofThere are limited primitive elements such as , but you should be aware that these operators still work because they exist in the output of the type-cleared code.
For example typeof (new Car())The CarI "Car"and not "object"Is.


So far it has been an overview, here handbookor read the Playground exampleExplore .

Translation of TS for JS Programmers.md

title: TypeScript for JavaScript Programmers
short: TypeScript for JS Programmers
layout: docs
permalink: /ko/docs/handbook/typescript-in-5-minutes.html

oneline: Learn how TypeScript extends JavaScript

The relationship between TypeScript and JavaScript in modern programming languages is somewhat unique.
TypeScript sits on top of JavaScript as a layer, providing the functionality of JavaScript while adding its own layer on top of it. This layer is the TypeScript type system.

JavaScript is already string, number, object, undefined It has the same primitive type, but it doesn't check in advance that it is assigned consistently to the entire codebase. TypeScript acts as this layer.

This means that JavaScript code that already exists and works well is TypeScript code at the same time, but TypeScript's Type Inspector can highlight the discrepancy between what you think and what JavaScript actually does.

This tutorial provides a 5-minute overview of the type system with a focus on understanding the type system language extensions that TypeScript adds.

Types by Inference

TypeScript knows the JavaScript language and will generate types in most cases.
For example, if you create a variable and assign it to a specific value at the same time, TypeScript will use that value as the type of that variable.

let helloWorld = "Hello World";
//  ^?

By understanding how JavaScript works, TypeScript can build a type system that accepts JavaScript code and has types. It provides a type system that eliminates the need to use additional characters to specify the type in the code. This is why in the example above the TypeScript is helloWorldprice stringThis is how you will find out.

You've probably been using VS Code with JavaScript and using the editor's autocomplete feature when you're working.
This is because an understanding of JavaScript, which is indispensable to TypeScript, has been used internally to improve JavaScript work.

Defining Types

JavaScript is a dynamic language that enables a variety of design patterns. Some design patterns may not be able to provide types automatically (because you're probably using dynamic programming), in which case TypeScript supports an extension of the JavaScript language that allows TypeScript to specify what a type should be.

Here's how to name: stringand id: numberAn example of creating an object with an inference type that includes .

const user = {
  name: "Hayes",
  id: 0,
};

To explicitly indicate the form of this object interface Declare it as.

interface User {
  name: string;
  id: number;
}

Now after the variable declaration : TypeNameUsing the syntax of a new JavaScript object interfaceYou can declare that you are following the form of .

interface User {
  name: string;
  id: number;
}
// ---cut---
const user: User = {
  name: "Hayes",
  id: 0,
};

If you create an object that doesn't fit that interface, TypeScript warns.

// @errors: 2322
interface User {
  name: string;
  id: number;
}

const user: User = {
  username: "Hayes",
  id: 0,
};

Because JavaScript supports class- and object-oriented programming, TypeScript is the same. - Interfaces can also be declared as classes.

interface User {
  name: string;
  id: number;
}

class UserAccount {
  name: string;
  id: number;

  constructor(name: string, id: number) {
    this.name = name;
    this.id = id;
  }
}

const user: User = new UserAccount("Murphy", 1);

Interfaces are also used to specify parameters and return values in functions.

// @noErrors
interface User {
  name: string;
  id: number;
}
// ---cut---
function getAdminUser(): User {
  //...
}

function deleteUser(user: User) {
  // ...
}

There are already a small number of primitive types available in JavaScript: boolean, bigint, null, number, string, symbol, objectand undefinedis available in the interface. TypeScript expands the list by adding a few things. For example any (allows anything), unknown (Make sure the person using this type has declared what the type is), never (This type cannot be generated) void (undefinedor a function that returns or has no return value).

You'll see pretty quickly that there are two constructs for building types: Interfaces and Types - interfaceand when you need a specific feature typemust be used.

Composing Types

Similar to how to combine objects to create larger, more complex objects, TypeScript has tools to do this with types.
The two most commonly used code in everyday code to create new types using different types are Union and Generic.

Union

A union is a way of declaring that a type can be one of several types. For example boolean Type true or falseIt can be described as:

type MyBool = true | false;

Consultation: MyBoolIf you hover over it, boolean- It's a property of the structured type system, which we'll look at later.

One of the most popular uses of union types is when values are allowed as follows: string or numberof literalThe set is to describe:

type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;

Union provides a way to handle various types, for example array or stringThere may be a function that receives the .

function getLength(obj: string | string[]) {
  return obj.length;
}

TypeScript understands how variables change over time in your code, and you can use these checks to pick out types.

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 typeof obj === "string"Using the stringand arrayand TypeScript knows that the object is in a different code path.

function wrapInArray(obj: string | string[]) {
  if (typeof obj === "string") {
    return [obj];
//          ^?
  } else {
    return obj;
  }
}

Generics

You can learn more about the TypeScript generic system, but for a 1-minute high-level explanation, generics are a way to provide variables to types.

Arrays are a common example, and arrays without generics can contain anything. An array with generics can describe the values in an array.

type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;

You can declare your own type using generics:

// @errors: 2345
interface Backpack<Type> {
  add: (obj: Type) => void;
  get: () => Type;
}

// 이 줄은 TypeScript에 `backpack`이라는 상수가 있음을 알리는 지름길이며
// const backpack: Backpack<string>이 어디서 왔는지 걱정할 필요가 없습니다.
declare const backpack: Backpack<string>;

// 위에서 Backpack의 변수 부분으로 선언해서, object는 string입니다.
const object = backpack.get();

// backpack 변수가 string이므로, add 함수에 number를 전달할 수 없습니다.
backpack.add(23);

Structural Type System

One of the core principles of TypeScript is that type checking has a value _form_is to concentrate on.
This is sometimes called "duck typing" or "structured typing."

In a structured type system, if two objects have the same shape, they are considered the same.

interface Point {
  x: number;
  y: number;
}

function printPoint(p: Point) {
  console.log(`${p.x}, ${p.y}`);
}

// "12, 26"를 출력합니다
const point = { x: 12, y: 26 };
printPoint(point);

pointThe variable is PointAlthough never declared as a type, TypeScript can be used in type checking pointwith the form of PointCompare the forms of .
Since both are of the same form, it passes.

Form matching requires only a subset of the fields of the object to be matched.

// @errors: 2345
interface Point {
  x: number;
  y: number;
}

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 wrap it up correctly, structurally there is no difference in how a class and an object follow a form:

// @errors: 2345
interface Point {
  x: number;
  y: number;
}

function printPoint(p: Point) {
  console.log(`${p.x}, ${p.y}`);
}
// ---cut---
class VirtualPoint {
  x: number;
  y: number;

  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

const newVPoint = new VirtualPoint(13, 56);
printPoint(newVPoint); // prints "13, 56"

If all the necessary properties of an object or class exist, TypeScript will see them as consistent regardless of the implementation details.

Next Steps

This document is a high-level, 5-minute overview of the syntax and types of tools you use in your everyday code. From here:

Translation of TS for Functional Programmers.md

title: TypeScript for Functional Programmers
short: TS for Functional Programmers
layout: docs
permalink: /ko/docs/handbook/typescript-in-5-minutes-func.html

oneline: Learn TypeScript if you have a background in functional programming

TypeScript is designed to bring traditional object-oriented programs to the web.
Microsoft programmers use traditional object-oriented types in JavaScript
It began as an attempt to import. As it has been developed, TypeScript's
The type system evolved into model code written by native JavaScript scripters.
The resulting system is powerful, interesting, and messy.

This introduction is for Haskell or ML programmers who want to learn TypeScript
Created for. The Haskell type system and the TypeScript type system
Explain the difference.
In addition, the TypeScript type system that occurs in the modeling of JavaScript code
Describes its unique features.

This introduction does not cover object-oriented programming.
In fact, TypeScript's object-oriented programs are available in other popular languages that have OO capabilities.
Similar to a program.

Prerequisites

This introduction assumes that you are aware of the following:

  • Core concepts for programming in JavaScript.
  • The type syntax of the C-family languages.

If you want to learn the core concepts of JavaScript
JavaScript: The Good PartsWould recommend.
A call-by-value lexic-scope language with a lot of variability
If you know how to write a program, you can still not read the book.
It doesn't matter.
R4RS Schemeis a good example.

C++ programming languageThe
It's great to learn about C-style type syntax.
Unlike C++, TypeScript uses postfix types, for example: string x Instead of x: string.

Concepts not in Haskell

Built-in types

In JavaScript, you define 8 built-in types:

type explanation
Number Double-precision IEEE 754 floating-point.
String Unmodifiable UTF-16 strings.
BigInt An integer of any precision type.
Boolean true and false.
Symbol A unique value that you usually use as a key.
Null Equivalent to unit type.
Undefined Also equivalent to the unit type.
Object Something similar to a record.

For more information, see the MDN page..

TypeScript has native types that correspond to the built-in types:

  • number
  • string
  • bigint
  • boolean
  • symbol
  • null
  • undefined
  • object

Other important TypeScript types

type explanation
unknown Top-level type.
never Subtype.
Object literals yes { property: Type }
void Intended to be used as a return type undefined A subtype of .
T[] modifiable arrays, and also Array<T> Available as
[T, T] Fixed length but modifiable tuple
(t: T) => U function

Please note:

  1. The function syntax contains the parameter name. It's pretty hard to get used to!

    let fst: (a: any, d: any) => any = (a, d) => a;
    // 또는 좀 더 정확하게 말하자면:
    let snd: <T, U>(a: T, d: U) => U = (a, d) => d;
  2. The object literal type syntax is quite similar to the object literal value syntax:

    let o: { n: number; xs: object[] } = { n: 1, xs: [] };
  3. [T, T] The T[] is a subtype of . Unlike Haskell, tuples are not related to lists.

Boxed types

JavaScript is a method that allows programmers to access that type.
I've been boxing the primitive types it contains equally. For example, in primitive form
number and box form type NumberWhat's different about TypeScript
I've been reflecting.
The box shape type is very rarely needed when the method returns a primitive type.

(1).toExponential();
// 동등하게
Number.prototype.toExponential.call(1);

To call a method from a numeric literal, parenthesis the method to support the parser
Note that it must be put inside.

Gradual typing

Whenever TypeScript does not know the type of the expression, any Type
use. DynamicCompared with ,any is called a type in
It can also be called excessive.
It does not check the type every time it appears. For example any[]
It doesn't matter if you put any value in without checking it:

// tsconfig.json 파일에 "noImplicitAny": false 를 삽입, anys: any[]
const anys = [];
anys.push(1);
anys.push("oh no");
anys.push({ anything: "goes" });

and any Types can be used anywhere:

anys.map(anys[1]); // 오 안되죠, "oh no" 함수가 아닙니다.

any It can be contagious, too. — What if any If you initialize a variable with an expression of type,
The variable is also any Has a type.

let sepsis = anys[0] + anys[1]; // 어떤 의미로도 가능합니다.

TypeScript anyTo raise an error when providing :
tsconfig.jsonIn "noImplicitAny": true or "strict": truemust be set.

Structural typing

Although Haskell and most MLs don't type structurally,
Structured typing is a familiar concept for most functional programmers.
The basic form is quite simple:

// @strict: false
let o = { x: "hi", extra: 1 }; // 성공
let o2: { x: string } = o; // 성공

Here, the object literal { x: "hi", extra : 1 }Matched to
{ x : string, extra : number } There is. Two
A type has all the required properties and has a type that can be assigned to that property.
{ x : string } can be assigned to:
The remaining properties do not prevent allocation, {x : string}As a subtype of
Create.

Named types are just named in the type. For assignment, type aliases
One and interface type Two There is not much difference between them.
both p: string I have properties.
(However, type aliases differ in interfaces related to recursive definitions and type parameters.
It works.)

// @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();

Union

In TypeScript, union types are not tagged. To put it another way,
From Haskell data Unlike , unions do not make a distinction.
However, you can distinguish types by different properties or unions that use built-in tags.

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 {
    // 마지막으로, 다른 문자열로 변환합니다
    return s;
  }
}

string, Array and Function is a type predicate
Built-in, else Object types for branches are for convenience
It's a good idea to leave it at that.
However, it can generate unions that are difficult to distinguish at run time.
For new code, it's best to build only the distinct unions.

The following types have predicates:

type predicate
string typeof s === "string"
number typeof n === "number"
bigint typeof m === "bigint"
boolean typeof b === "boolean"
symbol typeof g === "symbol"
undefined typeof undefined === "undefined"
function typeof f === "function"
array Array.isArray(a)
object typeof o === "object"

Functions and arrays are objects at runtime, but know that they have their own predicates
Let's take note.

intersection

In addition to Union, TypeScript also has intersections:

type Combined = { a: number } & { b: string };
type Conflicting = { a: number } & { a: string };

Combined is as if it were written in a single object literal type.
a and b It has two properties: Interchange and union are recursive
By causing a crash in the case Conflicting.a: number & string Is.

Unit types

A unit type is a subtype of a primitive type that contains exactly one raw value.
For example, a string "foo" The Type "foo"have.
JavaScript has no built-in enums, so it has a well-known set of strings.
It's common to use it instead.
String literal type unions follow this pattern in TypeScript:

declare function pad(s: string, n: number, direction: "left" | "right"): string;
pad("hi", 10, "left");

Extensible with the compiler if needed_ — As a parent type
convert — From primitive type to unit type, stringIn "foo"to
It happens when it is modifiable, and when you use some modifiable variables properly,
It may not work:

// @errors: 2345
declare function pad(s: string, n: number, direction: "left" | "right"): string;
// ---cut---
let s = "right";
pad("hi", 10, s); // 오류: 'string'은 '"left" | "right"'에 할당할 수 없습니다.

You may see an error like this:

- "right": "right"
- s: string silver "right" When is assigned to a modifiable variable. string Can be extended to .
- string silver "left" | "right"Could not be assigned to .

scan be solved using type notation in , but
As a result: "left" | "right" A non-type variable
sThis will prevent it from being assigned to .

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 can deduce types, such as declaring variables.
There are a few obvious ways:

let s = "I'm a string!";

But if you've ever worked in another C-like language, you might not have expected it.
Type inference is possible in different ways:

declare function map<T, U>(f: (t: T) => U, ts: T[]): U[];
let sns = map((n) => n.toString(), [1, 2, 3]);

Here, in this example, n: numberIn addition, T and UBefore the call
Despite not being deduced.
indeed [1,2,3] to T=numberAfter deducing the ,
n => n.toString()As the return type of U=stringBy inferring that,
snsprice string[] Make sure you have a type.

Inference works in any order, but intellisense is only from left to right
Since it works, TypeScript works with arrays mapto declare the
Preferred:

declare function map<T, U>(ts: T[], f: (t: T) => U): U[];

Contextual typing also works recursively through object literals, otherwise
stringor numberIt works as a deducible unit type with .
And you can deduce the return type through the context:

declare function run<T>(thunk: (t: T) => void): T;
let i: { inference: string } = run((o) => {
  o.inference = "INSERT STATE HERE";
});

o The type of { inference: string } has been decided. because

  1. The declaration initializer is a declaration type: { inference: string }Accordingly
    The type is contextually defined.
  2. Since the return type of the call uses a contextual type for reasoning,
    The compiler is T={ inference: string }to deduce.
  3. Because the arrow function uses contextual types to specify a type for a parameter,
    The compiler is o: { inference: string }to provide.

While typing, o. After typing the ,
Properties along with other properties in the actual program inference to
It can be supplemented.
This feature is like an integrated type inference engine through TypeScript's reasoning
As it may seem, it is not.

Type aliases

The type alias is Haskell typeis a simple alias, as is the case with .
The compiler tries to use the alias name used in the source code
I try, but it doesn't always succeed.

type Size = [number, number];
let x: Size = [101.1, 999.9];

newtypeThe most similar to tagged intersection Is:

type FString = string & { __compileTimeOnly: any };

FStringThe compiler doesn't actually exist __compileTimeOnlyCalled
It's like a regular string, except that I think I have properties.
FStringis still stringCan be assigned to, but
The opposite means impossible.

Discriminated unions

dataThe most similar to , which is usually called a discriminant union in TypeScript,
A union of type with discriminant properties:

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; x: number }
  | { kind: "triangle"; x: number; y: number };

Unlike Haskell, tags or determinations are each just an attribute in an object type.
Unusual cases have the same properties as other unit types.
It's still a normal union type; Led | The
It is an optional part of the union type syntax. Plain JavaScript using Union
It is distinguishable by code:

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;
  }
}

area The return type of is number , which indicates that TypeScript is a function that is full
It's important to be aware of that. If some unusual cases are not covered,
area The return type of is number | undefined will be replaced by .

Also, unlike Haskell, common attributes appear in any union,
So it is useful to distinguish between multiple unions:

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-family languages, TypeScript allows the declaration of type parameters to be
Requires:

function liftArray<T>(t: T): Array<T> {
  return [t];
}

There is no requirement for case, but type parameters are usually single uppercase.
Type parameters behave similarly to type class constraints.
Can be limited to types.

function firstish<T extends { length: number }>(t1: T, t2: T): T {
  return t1.length > t2.length ? t1 : t2;
}

Because TypeScript can generally deduce type arguments from calls based on argument types.
It usually doesn't require type arguments.

Because TypeScript is structural, a name-based system requires as many type parameters as it does
Don't. In particular, make the function polymorphic
It doesn't have to be. Type parameters make the parameters the same type as
Like limiting type information Only to propagate
It should read:

function length<T extends ArrayLike<unknown>>(t: T): number {}

function length(t: ArrayLike<unknown>): number {}

First lengthIn T is not required; Referenced only once,
that it is not used to restrict the type of other parameters or return values.
Be aware.

Higher-kinded types

TypeScript has no type of supertype. Therefore, we do not allow you to:

function length<T extends ArrayLike<unknown>, U>(m: T<U>) {}

Point-free programming

Point-free programming is — Excessive use of curring and function synthesis
— This is possible in JavaScript, but can be verbose.
Since type inference for point-free programming in TypeScript often fails,
You will specify a type parameter instead of a value parameter.
The result is so verbose that you usually avoid point-free programming.
It's good.

Module system

import or exportExcept that the file containing is implicitly a module.
The modern module syntax in JavaScript is slightly similar to Haskell:

import { value, Type } from "npm-package";
import { other, Types } from "./local-package";
import * as prefix from "../lib/third-package";

you can import it into the commonjs module — node.js' module system
Modules used:

import f = require("single-function-package");

Export to the list:

export { f };

function f() {
  return g();
}
function g() {} // g is not exported

Or by marking them individually:

export function f { return g() }
function g() { }

The latter style is more common, but both are also within the same file.
Allowed.

readonly and const (readonly and const)

In JavaScript, modifiability is the default,
_reference_to declare that it is inmodifiable constYou can declare a variable with .
The reference target is still modifiable:

const a = [1, 2, 3];
a.push(102); // ):
a[0] = 101; // D:

TypeScript is additionally attached to the properties readonly You can use the controller.

interface Rx {
  readonly x: number;
}
let rx: Rx = { x: 1 };
rx.x = 12; // error

Mapped Type Readonly<T> All the properties readonly to
Create a following:

interface X {
  x: number;
}
let rx: Readonly<X> = { x: 1 };
rx.x = 12; // error

And to remove the method that is causing the side effect and prevent changes to the array index.
specific ReadonlyArray<T> Type
There is a special syntax for this type:

let a: ReadonlyArray<number> = [1, 2, 3];
let b: readonly number[] = [1, 2, 3];
a.push(102); // error
b[0] = 101; // error

Only const-assertions that operate on arrays and object literals
You can use:

let a = [1, 2, 3] as const;
a.push(102); // error
a[0] = 101; // error

However, these features are not basic functions, so the TypeScript code
You don't have to use it consistently.

Next Steps

This document contains an overview of the high level of syntax and types in everyday code. From here, you can refer to the following:

- Complete Handbook From start to finish Read (30m)
- Playground exampleTake a look.

Translation of By Example.md

title: Declaration Reference
layout: docs
permalink: /ko/docs/handbook/declaration-files/by-example.html

oneline: "How to create a d.ts file for a module"

Introduction

This guide is written to explain how to write a quality declaration file.
This guide shows some of the API documentation along with examples of using the API.
Describes how to write the corresponding declaration.

The examples usually get more complex towards the second half.

The Examples

Objects with Properties

document

Global Variables myLibThere is a function to create a greeting makeGreetingand
Indicates the number of greetings you have created so far numberOfGreetings There are properties.

code

let result = myLib.makeGreeting("hello, world");
console.log("The computed greeting is:" + result);

let count = myLib.numberOfGreetings;

declaration

To describe a type or value approaching in dot notation declare namespaceUse .

declare namespace myLib {
    function makeGreeting(s: string): string;
    let numberOfGreetings: number;
}

Overloaded Functions

document

getWidget The function returns a Widget by taking a number as an argument, or a string as an argument and returning a Widget array.

code

let x: Widget = getWidget(43);

let arr: Widget[] = getWidget("all of them");

declaration

declare function getWidget(n: number): Widget;
declare function getWidget(s: string): Widget[];

Reusable Types (Interfaces)

document

When specifying a greeting, be sure to GreetingSettings You must pass an object.
This object has the following properties:

1 - greeting: required string

2 - duration: Optional Time (milliseconds)

3 - color: optional string, e.g. '#ff00ff'

code

greet({
  greeting: "hello world",
  duration: 4000
});

declaration

To define a type with properties interfaceUse .

interface GreetingSettings {
  greeting: string;
  duration?: number;
  color?: string;
}

declare function greet(setting: GreetingSettings): void;

Reusable Types (Type Aliases)

document

Wherever a greeting is expected, string, stringA function that returns a , or Greeter You can pass the instance.

code

function getGreeting() {
    return "howdy";
}
class MyGreeter extends Greeter { }

greet("hello");
greet(getGreeting);
greet(new MyGreeter());

declaration

You can use a type alias as an abbreviation for a type:

type GreetingLike = string | (() => string) | Greeter;

declare function greet(g: GreetingLike): void;

Organizing Types

document

greeter The object can write logs to a file or display a warning window.
Log Options .log(...) Inside, the warning window option .alert(...) It can be passed inside.

code

const g = new Greeter("Hello");
g.log({ verbose: true });
g.alert({ modal: false, title: "Current Greeting" });

declaration

Use namespaces to structure types.

declare namespace GreetingLib {
    interface LogOptions {
        verbose?: boolean;
    }
    interface AlertOptions {
        modal: boolean;
        title?: string;
        color?: string;
    }
}

You can make nested namespaces into a single declaration:

declare namespace GreetingLib.Options {
    // Refer to via GreetingLib.Options.Log
    interface Log {
        verbose?: boolean;
    }
    interface Alert {
        modal: boolean;
        title?: string;
        color?: string;
    }
}

Classes

document

Greeter You can instantiate an object to create a greeter, or you can inherit from it to create a custom greeter.

code

const myGreeter = new Greeter("hello, world");
myGreeter.greeting = "howdy";
myGreeter.showGreeting();

class SpecialGreeter extends Greeter {
    constructor() {
        super("Very special greetings");
    }
}

declaration

To describe a class or a class-like object declare classUse .
A class can have properties and methods as well as constructors.

declare class Greeter {
    constructor(greeting: string);

    greeting: string;
    showGreeting(): void;
}

Global Variables

document

Global Variables foocontains the number of widgets that exist.

code

console.log("Half the number of widgets is " + (foo / 2));

declaration

To declare a variable declare varUse .
If the variable is read-only, declare constUse .
If the variable is a block-scope declare let You can also use it.

/** 존재하는 위젯의 수 */
declare var foo: number;

Global Functions

document

To show the user a greeting greet You can call the function.

code

greet("hello, world");

declaration

To declare a function declare functionUse .

declare function greet(greeting: string): void;

Generated by 🚫 dangerJS against 840594a

@Joy1590
Copy link
Contributor Author

Joy1590 commented Sep 28, 2022

@microsoft-github-policy-service agree

1 similar comment
@Joy1590
Copy link
Contributor Author

Joy1590 commented Sep 28, 2022

@microsoft-github-policy-service agree

@KunHwanAhn
Copy link
Contributor

Thank you for PR!! 🙇

But, the #167 issue is not only Everyday Types, but also other pages.

If you use the word fix #167, it closes the issue when this PR is merged, even though other pages are not fixed. 🙏

@Joy1590
Copy link
Contributor Author

Joy1590 commented Oct 4, 2022

@KunHwanAhn I used _[^*\s](?:[^*]*[^*\s])?_ this regex to verify every Italic grammar.

@dvlprsh
Copy link
Contributor

dvlprsh commented Oct 4, 2022

LGTM

@github-actions github-actions bot merged commit aaf48ce into microsoft:main Oct 4, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Oct 4, 2022

Merging because @dvlprsh is a code-owner of all the changes - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Korean] Korean document have weird expressions like '_제네릭_'
3 participants