-
Notifications
You must be signed in to change notification settings - Fork 133
[Korean] Fix weird expressions like '_제네릭_' #171
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
Conversation
Translation of DOM Manipulation.mdtitle: DOM Manipulation translatable: trueDOM Manipulation
|
| 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:
--jsxFactoryYou can use the options to specify which JSX factory function to use when releasing React JSX. (The default isReact.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:
- In React, built-in elements are strings (
React.createElement("div")) but the components it produces are (React.createElement(MyComponent)) not. - 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:
- Functional Components (FC)
- 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.
SFCType and its aliasesStatelessComponentis 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 --experimentalDecoratorstsconfig.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
xIf 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:
- The representation of each decorator is evaluated from top to bottom.
- 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(): calledDecorator Evaluation
How to apply decorators to various declarations in a class is well defined as follows:
- method, accessor or _Property Decorator_followed by _Parameter Decorator_applies to each instance member.
- method, accessor or _Property Decorator_followed by _Parameter Decorator_applies to each static member.
- _Parameter Decorator_applies to the constructor.
- _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:
- The constructor function of the class for a static member, or a prototype of the class for an instance member.
- Name of the member
- 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
getandsetUnable 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.getandsetCombining 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:
- A constructor function of a class for a static member or a prototype of a class for an instance member
- Name of the member
- 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:
- A constructor function of a class for a static member or a prototype of a class for an instance member
- 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-metadataA library is required.
reflect-metadataFor 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:
- A constructor function of a class for a static member or a prototype of a class for an instance member
- Name of the member
- 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-metadataA library is required.
reflect-metadataFor 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 --saveTypeScript 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 --emitDecoratorMetadatatsconfig.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 PointThe 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:
- You can't make a new top-level declaration to an enrichment -- you can only patch an existing declaration.
- 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.tspackage.json
{
"scripts": {
"build": "babel --out-file bundle.js main.ts"
},
}Using the Command Line Interface
npm run buildBrowserify
installation
npm install tsifyUsing the Command Line Interface
browserify main.ts -p [ tsify --noImplicitAny ] > bundle.jsUsing 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-typescriptUsing the Command Line Interface
duo --use duo-typescript entry.tsUsing 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-tsdefault 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-typescriptdefault 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@betaNote: Currently, jspm's TypeScript support is 0.16beta.
For more information: TypeScriptSamples/jspm
Webpack
installation
npm install ts-loader --save-devThe 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 forInstallClick- 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 = bOn the last line, TypeScript found an error.
The logic for the error comes from the logic of checking that the assignment is healthy:
bThe type isaCan it be assigned to a type? No. Why?- because
mThis is because the types of attributes are not compatible. Why? - because
bofmAttribute (string[]) isaofmAttribute (number[]) cannot be assigned. Why? - 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:
- If the library has to create a similar kind of function throughout the API every time, it becomes cumbersome.
- We have 3 overloads, i.e. for each case positive Have a type (or each
numberandstring) 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 asnumbersilver42Represents a number such as . JavaScript does not have a separate runtime value for integers, sointorfloatThere is no such thing as . All the numbers are simplynumberIsbooleansilvertrueandfalsehas 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 timestring,number,booleanUse 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 | stringUnion 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.
인터페이스 |
타입 |
|---|---|
|
인터페이스 확장하기
|
교집합을 통하여 타입 확장하기
|
|
기존의 인터페이스에 새 필드를 추가하기
|
타입은 생성된 뒤에는 달라질 수 없다
|
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 versions prior to TypeScript 4.2, the type alias name is used in the error message It may appear and, sometimes appears on behalf of an equivalent anonymous type (which in some cases may or may not be desirable). The interface always appears in the error message.
- The type alias is it cannot be included in a declaration merge but interfaces can be included.
- The interface is It is only used to declare the shape of an object, and cannot be used to give aliases to existing primitive types.
- The name of the interface is Always as it is An error message appears. However, this is only This is only true when that interface is used by name in the code.
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, ornullThis 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:
-
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." -
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,
toLowerCaseIs 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 functionIt 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 typescriptIf you run the above code, you will see the TypeScript compiler
tscis installed globally.
tscLocalnode_modulesIf you want to run it from a packagenpxOr 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.tsVoila!
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.tshello.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:
personanddateArguments no longer have type notation.- "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:
- Complete Handbook From start to finish Read (30 minutes)
- Playground exampleExplore .
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:
numberstringbigintbooleansymbolnullundefinedobject
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:
-
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;
-
The object literal type syntax is quite similar to the object literal value syntax:
let o: { n: number; xs: object[] } = { n: 1, xs: [] };
-
[T, T]TheT[]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
- The declaration initializer is a declaration type:
{ inference: string }Accordingly
The type is contextually defined. - Since the return type of the call uses a contextual type for reasoning,
The compiler isT={ inference: string }to deduce. - Because the arrow function uses contextual types to specify a type for a parameter,
The compiler iso: { 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 exportedOr 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; // errorMapped Type Readonly<T> All the properties readonly to
Create a following:
interface X {
x: number;
}
let rx: Readonly<X> = { x: 1 };
rx.x = 12; // errorAnd 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; // errorOnly 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; // errorHowever, 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.
- Objects with Properties
- Overloaded Function
- Reusable Types (Interfaces)
- Reusable Types (Type Aliases)
- Organizing Types
- Classes
- Global Variables
- Global Functions
The Examples
Objects with Properties
document
Global Variables
myLibThere is a function to create a greetingmakeGreetingand
Indicates the number of greetings you have created so farnumberOfGreetingsThere 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
GreetingSettingsYou 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 , orGreeterYou 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
greeterThe 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
GreeterYou 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
greetYou can call the function.
code
greet("hello, world");declaration
To declare a function declare functionUse .
declare function greet(greeting: string): void;|
@microsoft-github-policy-service agree |
1 similar comment
|
@microsoft-github-policy-service agree |
|
Thank you for PR!! 🙇 But, the #167 issue is not only If you use the word |
|
@KunHwanAhn I used |
|
LGTM |
|
Merging because @dvlprsh is a code-owner of all the changes - thanks! |





Fix #167