Skip to content

Translate 1 file to ko, playground - Structural Typing#87

Closed
yahma25 wants to merge 115 commits intomicrosoft:mainfrom
yahma25:Translation-to-ko-palyground-Structural-Typing
Closed

Translate 1 file to ko, playground - Structural Typing#87
yahma25 wants to merge 115 commits intomicrosoft:mainfrom
yahma25:Translation-to-ko-palyground-Structural-Typing

Conversation

@yahma25
Copy link
Contributor

@yahma25 yahma25 commented Jun 26, 2021

en

번역 리뷰 요청합니다: @yeonjuan @bumkeyy
ref #6

감사합니다 😄

zhongsp and others added 27 commits February 14, 2021 20:10
The word" Community" is commonly translated to "社区".
It reads cleaner with other nav items.
playground-Discriminate Types
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
Co-authored-by: Kibeom Kwon <kgbum2222@gmail.com>
@github-actions
Copy link
Contributor

Thanks for the PR!

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

Orta Therox and others added 23 commits August 2, 2021 16:53
…ound-Indexed-Types

Translate 1 file to ko. playground Indexed Types
…Support

Translate 1 file to ko - Mobile Support
Co-authored-by: YeonJuan <yeonjuan93@naver.com>
…ound-Discriminate-Types

Translate 1 file to ko. playground-Discriminate Types
…translation

[PT-BR] Translate file Introduction
Fix typo in 'opeartor' to 'operator'
…nd-3-7-syntax-and-messaging

Translate FR: playground/fr/3-7/Syntax and messaging
…nd-3-7-syntax-and-messaging-typo-fix

FR translation: fix typo
…ng.ts

Co-authored-by: YeonJuan <yeonjuan93@naver.com>
…ound-Nominal-Typing

Translate 1 file to ko, playground - Nominal Typing
…ound-Conditional-Types

Translate 1 file to ko playground - Conditional Types
…tructural-Typing' into Translation-to-ko-palyground-Structural-Typing
@github-actions
Copy link
Contributor

Translation of noResolve.md

display: "No Resolve"

oneline: "Disallow imports, requires or <reference>s from expanding the number of files TypeScript should add to a project."

By default, TypeScript import and <reference Examine the initial set of files for the directive and add these verified files to the program.

noResolveThis process does not occur if is set.
however importThe statement is checked to make sure it is still a valid module, so you must otherwise verify that it is met.

Translation of moduleResolution.md

display: "Module Resolution"

oneline: "Specify how TypeScript looks up a file from a given module specifier."

Specify a module resolution strategy: 'node' (Node.js) or 'classic' (used in TypeScript prior to the 1.6 release).
In modern code, classicyou will not need to use .

Module Resolutionhas a handbook reference page.

Translation of watchOptions.md

Watch Options

You can configure the how TypeScript --watch works. This section is mainly for handling case where fs.watch and fs.watchFile have additional constraints like on Linux. You can read more at Configuring Watch.

Translation of alwaysStrict.md

display: "Always Strict"

oneline: "Ensure 'use strict' is always emitted."

Ensures that your files are parsed in the ECMAScript strict mode, and emit "use strict" for each source file.

Strict ECMAScript mode was introduced in ES5 and provides behavior tweaks to the runtime of the JavaScript engine to improve performance, and makes a set of errors throw instead of silently ignoring them.

Translation of intro.md

header: Introduction to the TSConfig reference

firstLine: A TSConfig file in a directory indicates that the directory is the root of a TypeScript or JavaScript project...

A TSConfig file in a directory indicates that the directory is the root of a TypeScript or JavaScript project.
The TSConfig file can be a tsconfig.json or jsconfig.json, both have the same set of configuration variables.

This page covers all the different options available in a TSConfig file. There are over 100 options, and this page is not designed to be read from top to bottom. Instead, it has five main sections:

  • A categorized overview of all aspects of the compiler
  • The root fields to tell TypeScript which files are available
  • The fields compilerOptions, this is the majority of the document
  • The fields watchOptions, to fine-tune the "watch" mode (automatic refreshment)
  • The fields typeAcquisition, to fine-tune how types are added to JavaScript projects

If you start a TSConfig file from scratch, you might consider using tsc --init to initiate or use a TSConfig database.

Translation of Watch_and_Build_Modes_6250.md

display: "Watch Options"

TypeScript 3.8 shipped a new strategy for watching directories, which is crucial for efficiently picking up changes to node_modules.

On operating systems like Linux, TypeScript installs directory watchers (as opposed to file watchers) on node_modules and many of its subdirectories to detect changes in dependencies.
This is because the number of available file watchers is often eclipsed by the of files in node_modules, whereas there are way fewer directories to track.

Because every project might work better under different strategies, and this new approach might not work well for your workflows, TypeScript 3.8 introduces a new watchOptions field which allows users to tell the compiler/language service which watching strategies should be used to keep track of files and directories.

Translation of Introduction.md

title: Introduction
layout: docs
permalink: /pt/docs/handbook/declaration-files/introduction.html

oneline: "How to write a high-quality TypeScript Declaration File (d.ts) "

The Declaration Files section is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume a basic familiarity with the TypeScript language to begin with.

If you haven't already done so, you should read the Manual do TypeScript

The most common case for learning how .d.ts files work is when you are writing an npm package without types.
In this case, you can go straight to .d.ts modules.

The Declaration files section is divided into the following parts:

Declaration Reference

We often face the task of writing a claim file only when we have examples of the underlying library to guide us.
The section Declaration reference shows several common API patterns and how to write statements for each of them.
This guide is aimed at beginners in TypeScript who may not yet be familiar with all language constructs in TypeScript.

Library Structures

The guide Library Structures helps you understand common library formats and how to write an appropriate claim file for each format.
If you are editing an existing file, you probably do not need to read this section.
Authors of new declaration files strongly recommend reading this section to properly understand how the library format influences the writing of the claim file.

In the Template section you will find several claim files that serve as a useful starting point when writing a new file. If you already know its structure, see the Template d.ts section in the sidebar.

What to do and what not to do

Many common errors in claim files can be easily avoided.
The section What to do and what not to do identifies common errors,
describes how to detect them, and how to fix them.
Everyone should read this section to avoid common mistakes.

In-depth analysis

For experienced authors interested in the mechanics behind the declaration files,
the section In-depth analysis explains several advanced concepts in the writing of the statement,
and shows you how to leverage these concepts to create clean, more intuitive claim files.

Post to npm

The section Publication explains how to publish your claim files to an npm package, and how to manage your dependent packages.

Search for and install Claim Files

For javascript library users, the section Consumption offers a few steps to find and install matching claim files.

Translation of Do's and Don'ts.md

title: Do's and Don'ts
layout: docs
permalink: /pt/docs/handbook/declaration-files/do-s-and-don-ts.html

oneline: "Recommendations for writing d.ts files"

General Types

Number, String, Boolean, Symbol And Object

Never use the types Number, String, Boolean, Symbolor Object
These types reference non-primitive objects that are almost never used appropriately in JavaScript code.

/* Errado */
function reverte(s: String): String;

Always use the types number, string, booleanand symbol.

/* OK */
function reverte(s: string): string;

Instead of Object, use the non-primitive type object (added in TypeScript 2.2).

Generics

Never have a generic type that does not use the types of its parameters.
See more details at TypeScript FAQ page.

Any any

Never Use any as type unless you are in the process of migrating the javascript project to Typescript. The compiler effectively Comes any like "please turn off the type check for this thing". This is similar to putting a comment @ts-ignore around each use of the variable. This can be very useful when you are first migrating a JavaScript project to TypeScript because you can set the type for things you haven't migrated as any, but in a full TypeScript project you will be disabling type checking for any part of your program that uses it.

In cases where you don't know the type you want to accept, or when you want to accept anything because it will go on blindly without interacting, you can use unknown.

Callback Types

Return Types and Callbacks

Never use the return type any for callbacks whose value will be ignored:

/* ERRADO */
function fn(x: () => any) {
  x();
}

Always use the return type void for callbacks whose value will be ignored:

/* OK */
function fn(x: () => void) {
  x();
}

Why is that?: Using void is safer because it prevents you from accidentally using the return value of x in an unverified manner:

function fn(x: () => void) {
  var k = x(); // oops! deveria fazer outra coisa
  k.facaAlgo(); // erro, mas ficaria OK se o tipo retorno tivesse sido 'any'
}

Optional Parameters in Callbacks

Never use optional parameters on callbacks unless you actually have this intent:

/* ERRADO */
interface Buscador {
  retornaObjeto(pronto: (data: any, tempoDecorrido?: number) => void): void;
}

This has a very specific meaning: the callback pronto can be invoked with 1 argument or can be invoked with 2 arguments.
The author probably intended to say that the callback might not care about the parameter tempoDecorrido, but you don't need to do the optional parameter to achieve this --
it is always valid to provide a callback that accepts a smaller number of arguments.

Always write callback parameters as non-optional:

/* OK */
interface Buscador {
  retornaObjeto(pronto: (data: any, tempoDecorrido: number) => void): void;
}

Overloads and Callbacks

Never write separate overloads that differ only in the arity of the callback:

/* ERRADO */
declare function antesDeTodos(acao: () => void, timeout?: number): void;
declare function antesDeTodos(
  acao: (done: DoneFn) => void,
  timeout?: number
): void;

Always write a single overload using the maximum arity:

/* OK */
declare function antesDeTodos(
  acao: (done: DoneFn) => void,
  timeout?: number
): void;

Why is that?: It is always valid for a callback to disregard a parameter, so there is no need to shorten the overhead.
Providing a shorter callback first allows incorrectly typed functions to be passed forward because they match the first overload.

Function Overloads

Ordination

Never put mental overloads before the most specific:

/* ERRADO */
declare function fn(x: any): any;
declare function fn(x: HTMLElement): number;
declare function fn(x: HTMLDivElement): string;

var meuElem: HTMLDivElement;
var x = fn(meuElem); // x: any, quê?

Always order overloads by placing the most generic signatures after the most specific ones:

/* OK */
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: any): any;

var meuElem: HTMLDivElement;
var x = fn(meuElem); // x: string, :)

Why is that?: TypeScript chooses the first overload with matching when resolving calls to functions.
When a newer overload "is more general" than an older one, the oldest one is effectively omitted and cannot be called.

Use Optional Parameters

Never write many overloads that differ only in the final parameters:

/* ERRADO */
interface Exemplo {
  diff(um: string): number;
  diff(um: string, dois: string): number;
  diff(um: string, dois: string, tres: boolean): number;
}

Always optional parameters:

/* OK */
interface Exemplo {
  diff(um: string, dois?: string, tres?: boolean): number;
}

Note that this collapse should occur only when all overloads have the same return type.

Why is that?: This is important for two reasons.

TypeScript resolves signature compatibility by verifying that any target signatures can be called with the source arguments,and strange arguments are allowed.
This code, for example, exposes a bug only when the signature is written correctly using optional parameters:

function fn(x: (a: string, b: number, c: number) => void) {}
var x: Exemplo;
// Quando escrito com sobrecarga, OK -- usado a primeira sobrecarga
// Quando escrito com opcionais, devidamente um erro
fn(x.diff);

The second reason is when a consumer uses TypeScript's "strict null checking" functionality.
Because unspecified parameters appear as undefined in javascript, it's usually good to spend a undefined for a function with optional arguments.
This code, for example, should be OK under strict nulls:

var x: Exemplo;
// Quando escrito com sobrecargas,  um erro porque passa 'undefined' para 'string'
// Quando escrito com opcionais, devidamente OK
x.diff("algo", true ? undefined : "hora");

Use Union Types

Never write overloads that differ by type in just one argument:

/* ERRADO */
interface Momento {
  utcOffset(): number;
  utcOffset(b: number): Momento;
  utcOffset(b: string): Momento;
}

Always possible to use union types:

/* OK */
interface Momento {
  utcOffset(): number;
  utcOffset(b: number | string): Momento;
}

Realize we didn't b optional here because the return types of signatures are different.
Why is that?: This is important for people who are "passing on" a value for their role:

function fn(x: string): void;
function fn(x: number): void;
function fn(x: number | string) {
  // Quando escrito com sobrecargas separadas, indevidamente um erro
  // Quando escrito com tipos de união, 
  // When written with union types, devidamente OK
  return momento().utcOffset(x);
}
Translation of Deep Dive.md

title: In-depth analysis
layout: docs
permalink: /pt/docs/handbook/declaration-files/deep-dive.html

oneline: "How d.ts files work, a deep analysis"

Statement file theory: An in-depth analysis

Structuring modules to get the exact shape of the API you want can be tricky.
For example, we might want a module that can be invoked with or without new to produce different types,
that has a variety of named types exposed in a hierarchy,
and that has some properties on the module object as well.

By reading this guide, you will have the tools to write complex claim files that expose a user-friendly API.
This guide focuses on module libraries (or UMD) because the options are more varied.

Key concepts

You can perfectly understand how to create any form of declaration
by understanding some key concepts of how TypeScript works.

Types

If you're reading this guide, you probably already know superficially what a type is in TypeScript.
To be more explicit, however, a kind is entered with:

  • A declaration of type alias (type sn = number | string;)
  • An interface declaration (interface I { x: number[]; })
  • A class declaration (class C { })
  • An enum declaration (enum E { A, B, C })
  • A statement import that refers to a type

Each of these claim shapes creates a new type name.

Values

Just like types, you probably already understand what a value is.
Values are runtime names that we can reference in expressions.
For instance let x = 5; creates a value called x.

Again, being explicit, the following items create values:

  • Statements let, const and var
  • A statement of namespace or module that contains a value
  • A statement of enum
  • A statement of class
  • A statement import that refers to a value
  • A statement of function

Namespaces

Types can exist in namespaces.
For example, if we have the statement let x: A.B.C,
we say that the kind C comes from the namespace A.B.

This distinction is subtle and important -- here, A.B is not necessarily a type or a value.

Simple combinations: One name, multiple meanings

Given a name A, we can find up to three meanings for A: A type, value, or namespace.
How the name is interpreted depends on the context in which it is used.
For example, in the declaration let m: A.A = A;,
A it is used first as a namespace, then as a type name, and then as a value.
These meanings may end up referring to totally different statements!

This may seem confusing, but it's very convenient as long as we don't overburden things.
Let's look at some useful aspects of this behavior combination.

Integrated combinations

Attentive readers will note that, for example, class appeared on both lists of kind and value.
The statement class C { } creates two things:
one kind C which refers to the form of the class instance,
and a value C that refers to the class's constructor function.
Declaration of enums behave similarly.

User combinations

Let's say we write a module file foo.d.ts:

export var SomeVar: { a: SomeType };
export interface SomeType {
  count: number;
}

Next, we use:

import * as foo from "./foo";
let x: foo.SomeType = foo.SomeVar.a;
console.log(x.count);

This works well, but we can imagine that SomeType and SomeVar are closely related
so that you would like them to have the same name.
We can use the combination to present these two different objects (the value and the type) under the same name Bar:

export var Bar: { a: Bar };
export interface Bar {
  count: number;
}

This presents a very good opportunity for destructuring in the code that uses it:

import { Bar } from "./foo";
let x: Bar = Bar.a;
console.log(x.count);

Again, we use the Bar here as type and value.
Realize that we don't need to declare the value Bar as being of the kind Bar - they're independent.

Advanced combinations

Some claim types can be combined through multiple declarations.
For instance class C { } and interface C { } can coexist and both contribute properties to the types C.

This is allowed as long as a conflict is not created.
A general rule of all, values always conflict with other values of the same name unless they are declared as namespaces,
conflict types if they are declared with a type alias (type s = string),
and namespaces never conflict.

Let's see how this can be used.

Add using a interface

We can add additional members to a interface with another statement of interface:

interface Foo {
  x: number;
}
// ... em outro local ...
interface Foo {
  y: number;
}
let a: Foo = ...;
console.log(a.x + a.y); // OK

This also works with classes:

class Foo {
  x: number;
}
// ... em outro local ...
interface Foo {
  y: number;
}
let a: Foo = ...;
console.log(a.x + a.y); // OK

Note that we cannot add to the type alias (type s = string;) using an interface.

Add using a namespace

A statement of namespace you can use to add new types, values, and namespaces in any way that does not create conflicts.

For example, we can add a static member to a class:

class C {}
// ... em outro local ...
namespace C {
  export let x: number;
}
let y = C.x; // OK

Note that in this example, we add a value to the static from C (its construction function)
This is because we have added a value, and the container for all values is another value
(types are contained by namespaces), and namespaces are contained by other namespaces).

We can also add a type with namespace to a class:

class C {}
// ... em outro local ...
namespace C {
  export interface D {}
}
let y: C.D; // OK

In this example, there was no namespace C until we write a statement of namespace to him.
The meaning of C as a namespace does not conflict with the meanings of value or type of C created by the class.

Finally, we can perform different merges using namespace.
This is not a particularly realistic example, but shows several types of interesting behaviors:

namespace X {
  export interface Y {}
  export class Z {}
}

// ... em outro local ...
namespace X {
  export var Y: number;
  export namespace Z {
    export class C {}
  }
}
type X = string;

In this example, the first block creates the following name meanings:

  • A value X (because the declaration of namespace contains a value, Z)
  • A namespace X (because the declaration of namespace contains a type, Y)
  • A type Y in the namespace X
  • A type Z in the namespace X (the shape of the class instance)
  • A value Z which is a property of value X (the class constructor function)

The second block creates the following name meanings:

  • A value Y (of the type number) which is a property of the value X
  • A namespace Z
  • A value Z which is a property of value X
  • A type C in the namespace X.Z
  • A value C which is a property of value X.Z
  • A type X
Translation of By Example.md

title: Declaration Reference
layout: docs
permalink: /pt/docs/handbook/declaration-files/by-example.html

oneline: "How to create a d.ts file for a module"

The purpose of this guide is to teach you how to write a high-quality definition file.
The structure of this guide displays documentation for an API, along with usage samples and explanations of how to write the corresponding claim.

These examples are ordered in an approximate ascending order of complexity.

Objects with Properties

Documentation

The global variable minhaLib has a function criaCumprimento to create greetings,
and a property numeroDeCumprimentos indicating the number of compliments made there.

Code

let resultado = minhaLib.criaCumprimento("Olá, mundo");
console.log("O cumprimento computado é:" + resultado);

let count = minhaLib.numeroDeCumprimentos;

Statement

Use declare namespace to describe types or values accessed via peer notation.

declare namespace minhaLib {
  function criaCumprimento(s: string): string;
  let numeroDeCumprimentos: number;
}

Overloaded Functions

Documentation

The function pegaFerramenta accepts a number and returns a Tool, or accepts a string and returns an array of Tools.

Code

let x: Ferramenta = pegaFerramenta(43);

let arr: Ferramenta[] = pegaFerramenta("todas");

Statement

declare function pegaFerramenta(n: number): Ferramenta;
declare function pegaFerramenta(s: string): Ferramenta[];

Reusable Types (Interfaces)

Documentation

When specifying a greeting, you must pass an object ConfiguracoesCumprimento.
This object has the following properties:

1 - greeting: String required

2 - duration: Optional length of time (in milliseconds)

3 - color: Optional string, e.g. '#ff00ff'

Code

cumprimenta({
  cumprimento: "olá mundo",
  duracao: 4000
});

Statement

Use a interface to define a type with properties.

interface ConfiguracoesCumprimento {
  cumprimento: string;
  duracao?: number;
  cor?: string;
}

declare function cumprimenta(setting: ConfiguracoesSaudacao): void;

Reusable types (Aliasetype)

Documentation

Anywhere a greeting is expected, you can provide a string, a function returning a string, or an instantiation of Cumprimentador.

Code

function pegaCumprimento() {
  return "oopa";
}
class MeuCumprimentador extends Cumprimentador {}

cumprimenta("olá");
cumprimenta(pegaCumprimento);
cumprimenta(new MeuCumprimentador());

Statement

You can use an alias to make an abbreviation for a type:

type ComoUmCumprimentador = string | (() => string) | MeuCumprimentador;

declare function cumprimenta(g: ComoUmCumprimentador): void;

Organizing Types

Documentation

The object cumprimentador can log to a file or show an alert.
You can provide LogOptions for .log(...) and alert options for .alert(...)

Code

const g = new Cumprimentador("Olá");
g.log({ verbose: true });
g.alert({ modal: false, title: "Cumprimento Atual" });

Statement

Use namespaces to organize types.

declare namespace CumprimentoLib {
  interface LogOptions {
    verbose?: boolean;
  }
  interface AlertOptions {
    modal: boolean;
    title?: string;
    color?: string;
  }
}

You can also create nested namespaces in a declaration:

declare namespace CumprimentoLib.Options {
  // Faz referência via CumprimentoLib.Options.Log
  interface Log {
    verbose?: boolean;
  }
  interface Alert {
    modal: boolean;
    title?: string;
    color?: string;
  }
}

Classes

Documentation

You can create a greeter by instantiating the object Cumprimentador, or when creating a customized greeter when extending it.

Code

const MeuCumprimentador = new Cumprimentador("Olá, mundo");
MeuCumprimentador.cumprimento = "oopa";
MeuCumprimentador.mostraCumprimento();

class CumprimentadorEspecial extends Cumprimentador {
  constructor() {
    super("Cumprimentador muito especial");
  }
}

Statement

Use declare class to describe a class or object similar to the class.
Classes can also have properties and methods as well as a constructor.

declare class Cumprimentador {
  constructor(cumprimento: string);

  cumprimento: string;
  mostraCumprimento(): void;
}

Global Variables

Documentation

The global variable foo contains the current number of tools.

Code

console.log("Metade do numero de ferramentas é " + foo / 2);

Statement

Use declare var to declare variables.
If the variable is read-only, you can use declare const.
You can also use declare let whether the variable is scope-closed.

/** O numero de ferramentas atual */
declare var foo: number;

Global Functions

Documentation

You can call the function cumprimenta with a string to show a greeting to the user.

Code

cumprimenta("olá, mundo");

Statement

Use declare function to declare functions.

declare function cumprimenta(cumprimento: string): void;
Translation of React.md

title: React
layout: docs
permalink: /fr/docs/handbook/react.html
oneline: Links to learn more about TypeScript and React

translatable: true

TypeScript supports JSX and can correctly model the conventions used in React code bases such as useState.

Setting up a React project

Today, there are many frameworks that support TypeScript independently:

All these elements are excellent starting points. We use Gatsby with TypeScript for this website, which can also be a useful reference implementation.

Documentation

Here are some of the best places to find up-to-date information about React and TypeScript:

Translation of Angular.md

title: Angular
layout: docs
permalink: /fr/docs/handbook/angular.html
oneline: Using Angular with TypeScript

deprecated: true

Angular is a modern framework built entirely in TypeScript and, therefore, using TypeScript with Angular provides a smooth experience.

Angular's documentation not only puts TypeScript first, but also uses it as its main language.
With this in mind, Angular's website will always be the most up-to-date reference for using Angular with TypeScript.

Consult the quick start guide here to start learning Angular now!

Translation of Nightly Builds.md

title: Nightly Builds
layout: docs
permalink: /fr/docs/handbook/nightly-builds.html
oneline: How to use a nightly build of TypeScript

translatable: true

A nightly build of the branch Typescript main is published before midnight PST on npm.
Here's how you can get it and use it with your tools.

Using npm

npm install -g typescript@next

Update your IDE to use nightly builds

You can also update your IDE to use the nightly build.
You will first need to install the package via npm.
You can either install the npm package globally or in a local folder node_modules.

The rest of this section assumes that typescript@next is already installed.

Visual Studio Code

Update .vscode/settings.json with the following:

"typescript.tsdk": "<chemin vers votre dossier>/node_modules/typescript/lib"

More information is available on the VSCode documentation.

Sublime Text

Update the file Paramètres - Utilisateur with the following:

"typescript_tsdk": "<chemin vers votre dossier>/node_modules/typescript/lib"

More information is available in the TypeScript plug-in installation documentation for Sublime Text.

Visual Studio 2013 and 2015

Note: Most changes do not require the installation of a new version of the VS TypeScript plug-in.

The nightly build does not currently include the full configuration of the plug-in, but we are also working on the release of a nigthly installer.

  1. Download the script VSDevMode.ps1.

    See also our wiki page on using a custom language service file.

  2. From a PowerShell command window, run:

For VS 2015:

VSDevMode.ps1 14 -tsScript <chemin vers votre dossier>/node_modules/typescript/lib

For VS 2013:

VSDevMode.ps1 12 -tsScript <chemin vers votre dossier>/node_modules/typescript/lib

IntelliJ IDEA (Mac)

Go to Préférences > Langues & Frameworks > TypeScript :

TypeScript version: If you installed with npm: /usr/local/lib/node_modules/typescript/lib

IntelliJ IDEA (Windows)

Go to Fichier > Paramètres > Langues & Frameworks > TypeScript :

TypeScript version: If you installed with npm: C:\Users\USERNAME\AppData\Roaming\npm\node_modules\typescript\lib

Translation of Watch_and_Build_Modes_6250.md

display: "Listen options"

TypeScript 3.8 provides a new strategy for listening to directories, which is effective for getting node_modules changes to are critical.

On linux-like operating systems, TypeScript will be available node_modules Directory listening (not file listening) is initiated on its subdirectories to detect changes in dependencies. This is because node_modules The number of files in is large, often exceeding the maximum number of file listens allowed by the system, while the directories that need to be listened to are much smaller.

TypeScript 3.8 introduces a new approach that may not be appropriate for your workflow because of the environment and requirements of different projects watchOptions Fields that allow users to tell compilers or language services which policies should be used to track file and directory changes.

Translation of Watch_and_Build_Modes_6250.md

display: "Watch Options"

TypeScript 3.8 has launched a new strategy to monitor folders, which is crucial to achieving changes in node_modules.

On operating systems such as Linux, Typescript installs directory monitors (unlike file monitors) on the node_modules and many of its sub-directories to detect changes in their dependencies.
This is due to the amount of available file monitors that is eclipsed by the number of files in the node_modules, while there are very few directories to crawl.

Because each project should work best with different strategies, and this new approach may not work for your workflow, TypeScript 3.8 introduced the new field watchOptions that allows the user to tell the compiler/language service which monitoring strategies should be used to keep track of directories and files.

Translation of Watch_and_Build_Modes_6250.md

display: "Watch Options"

A new strategy for monitoring directories has been released in TypeScript 3.8. This isnode_modules is critical to efficiently detecting changes in

In operating systems like Linux, TypeScript detects dependency changes.node_modules and install directory watchers (not file watchers) in many subdirect directories.
Because the number of file watchers available,node_modules often more files, but fewer directories are tracked.

Each project may work better under a different strategy, and conversely, this new approach may not work well with a series of work flows. Therefore, typescript 3.8 watchOptions Fields have been introduced. In this field, you can tell the compiler/language service which monitoring strategy to use to track files and directories.

Translation of Watch_and_Build_Modes_6250.md

display: "Surveillance Options"

TypeScript 3.8 comes with a new strategy for overseeing directories, crucially determining changes efficiently to the directory. node_modules.

On operating systems such as Linux, TypeScript installs a supervisory directory (rather than a file supervisor) on node_modules and many directories in it to detect changes to dependencies.
This is because the number of file supervisors often exceeds the files contained in the file. node_modules, while there are fewer directories to keep an eye on.

Since each project might work with a different strategy, and this new approach may not work well with your workflow, TypeScript 3.8 introduces options. watchOptions Which allows users to tell the compiler/service which surveillance strategy language should be used to oversee files and directories.

Translation of Watch_and_Build_Modes_6250.md

display: "Surveillance Options"

TypeScript 3.8 launched a new strategy for parsing directories, which is crucial for efficiently detecting changes to directories. node_modules.

On operating systems such as Linux, TypeScript installs directory watchdogs (as opposed to file watchdogs) on node_modules and many of its subdirectories to detect changes in dependencies.
This is because the number of available file watchdogs is often overshadowed by the number of files in node_modules, while there are far fewer directories to crawl.

because each project might work better under different strategies and this new approach might not work well for your workflows typescript 3.8 introduces a new field watchOptions which allows users to tell the compiler/language service which surveillance strategies should be used to keep track of files and directories.

Translation of Project References.md

title: Project References
layout: docs
permalink: /ko/docs/handbook/project-references.html
oneline: How to split up a large TypeScript project

translatable: true

Project Reference is a new feature in TypeScript 3.0 that allows you to organize TypeScript programs into smaller pieces.

This greatly improves build time and forces logical separation between components, allowing you to organize your code in new and better ways.

It also works with project references for fast TypeScript builds. tsc new mode of --build Flags have been introduced.

An Example Project

Let's look at a fairly generic program and see how project references can help you better organize it.
converterand unitsImagine that two modules are in the project, and each module has a corresponding test file:

/src/converter.ts
/src/units.ts
/test/converter-tests.ts
/test/units-tests.ts
/tsconfig.json

The test file imports the implementation file and proceeds with the test:

// converter-tests.ts
import * as converter from "../converter";

assert.areEqual(converter.celsiusToFahrenheit(0), 32);

Previously, this structure worked awkwardly when using a single tsconfig file:

  • It is possible to import a test file from an implementation file
  • I probably didn't want to. srcdoes not appear in the output folder name. testand srcIt is not possible to build at the same time
  • In the implementation file Contents it never causes new errors, but _Type checking_You'll need to do it again
  • Changing the test file alone doesn't change anything, but you'll need to recheck the type of the implementation file

Of these issues, you can use multiple tsconfig files _Some_Can be solved, but a new problem occurs:

  • As there is not the latest built-in inspection, it is always tscmust be run twice
  • tscCalling twice results in more startup time overhead
  • tsc-wcannot run multiple config files at once

Project references can solve all these problems.

What is the project reference? (What is a Project Reference?)

tsconfig.json The file contains a new top-level property reference. This is an array of objects that specify the project to reference:

{
    "compilerOptions": {
        // The usual
    },
    "references": [
        { "path": "../src" }
    ]
}

Each reference's path Properties tsconfig.json Point to the directory that has the file, or point to the config file itself (which can have any name).

When you refer to a project, something new happens:

  • When you import a module from a referenced project, you output Load the declaration file instead (.d.ts)
  • If the project referenced outFile, the output file .d.ts The declaration of the file is exposed within this project
  • Build mode (see below) builds projects that are automatically referenced if necessary

Separating into multiple projects greatly improves the speed of type checking and compilation, reduces memory usage when using the editor, and improves logical grouping of programs.

composite

The referenced project is surely new composite The setting must be enabled.
This setting is required to help TypeScript quickly determine where to find the output of the referenced project.
composite When you activate a flag, several things change:

  • What if rootDir If the setting is not explicitly specified, the default value is tsconfig The directory with the file
  • All implementation files must be include Fit the pattern, files It must be inside an array. If you violate this constraint, tsctells you which files are not specified
  • declarationmust be turned on

declarationMaps

Declaration Source MapAdded support for .
What if --declarationMapWith , you can use editor features such as "Go to Definition" and Rename to navigate transparently in supported editors and modify code across project boundaries.

prependand outFile (prepend with outFile)

In reference prepend You can enable appending the output of a dependency using the option:

   "references": [
       { "path": "../utils", "prepend": true }
   ]

Adding a project includes the output of the project above the output of the current project.
This is .js Files .d.ts It works for all files, and the source map file is also ejected correctly.

tscuses only existing files on disk for this task, so it is possible to create a project where the correct output file cannot be generated, because the output of a project may appear in the resulting file more than once.
For example:

   A
  ^ ^
 /   \
B     C
 ^   ^
  \ /
   D

In this situation, it is important not to add to each reference, because DIn the output of the AThis is because there are two copies of - this can have unexpected consequences.

Caveats for Project References

There are several tradeoffs that project references must be noted.

Because dependency projects are built from dependencies, .d.ts Because you use a file, you can check the specific build output before you can navigate the project without seeing any incorrect errors in the editor, or or After the clone, you need to build the project.
We're working on a process to create .d.ts that can improve this, but for now, we recommend that developers build after clones.

Additionally, to maintain compatibility with existing build workflows, tsc --build Do not build dependencies automatically unless you call a switch Is.
--buildLet's learn about .

Build mode for TypeScript (Build Mode for TypeScript)

The long-awaited feature is a smart incremental build for typeScirpt projects.
In 3.0 tscIn --build Flags are now available.
This behaves more like a build manager than a simple compiler. tscthe new entry point for .

tsc --build (The informal tsc -b) to do the following:

  • Find all referenced projects
  • Detects if it is up to date
  • Build non-up-to-date projects in the correct order

tsc -bYou can provide multiple config file paths (for example. tsc -b src test).
tsc -pLike, if the config file name tsconfig.json, you do not need to specify a name.

tsc -b Command line (tsc -b Commandline)

You can specify as many config files as you want:

 > tsc -b                            # 현재 디렉터리에 있는 tsconfig.json 사용
 > tsc -b src                        # src/tsconfig.json 사용
 > tsc -b foo/prd.tsconfig.json bar  # foo/prd.tsconfig.json 와 bar/tsconfig.json 사용

Don't worry about the order of the files you passed to the command line - if necessary tscbecause rearranges, dependencies are always built first.

tsc -bThere are several more flags that you can specify in :

  • --verbose: Outputs detailed log of how it is progressing (can be combined with other flags)
  • --dry: Doesn't actually build, but shows what's going to happen
  • --clean: Removes the output of the specified project (--drycan be combined with)
  • --force: All projects behave as if they are not up-to-date
  • --watch: Surveillance mode (--verbosecannot be combined with any other flag except )

Cautions (Caveats)

generally tsc noEmitOnErrorif is not enabled, the output (.jsand .d.ts) to create a .
It's not very good to do this on an incremental build system - because if one of the non-up-to-date dependencies has a new error, you'll skip building a project where the next build is currently up-to-date. once You can only see it.
For this reason, tsc -b noEmitOnErrorbehaves as effectively as if it were active in all projects.

No build output (.js, .d.ts, .d.ts.map, etc.), depending on whether the source control tool preserves the timestamp between the local and remote copies. --force You may need to run the build.

MSBuild

If you have an msbuild project, add the following to the proj file for build mode:

    <TypeScriptBuildMode>true</TypeScriptBuildMode>

you can activate it. This enables automatic incremental builds as well as removal.

tsconfig.json / -pAs with , note that existing TypeScript project properties are not considered - all settings must be managed using the tsconfig file.

Some teams may want to work together to create projects where the tsconfig files are Implicit It has a graph order and has set up an msbuild-based workflow.
If the solution is the same, msbuild tsc -pand continue to be used; They are fully interoperable.

Guidance

Overall Structure

More tsconfig.json to centrally control common compiler options. Inherit configuration filesyou'll want to use .
This way, you can change the settings in one file without modifying multiple files.

Another good way is simply to referenceshave a files"Solution" to set to an empty array tsconfig.json It's about having a file (otherwise, the file will be compiled twice because of the solution file). At least one from 3.0 referenceprice tsconfig.jsonif you are in, files Note that having an array is no longer an error.

This provides a simple entry point; For example, in the TypeScript store, src/tsconfig.json simply because it lists all the subprojects in tsc -b src run and build all endpoints.

These patterns can be found in the TypeScript repository - as a main example src/tsconfig_base.json, src/tsconfig.jsonand src/tsc/tsconfig.jsonLook at .

Structuring for relative modules

In general, you don't need much else to switch stores using relative modules.
Simply parent of the folder tsconfig.json Place the file within each subdirectory and match the intended hierarchy of the program. referenceto this config file.
outDiras an explicit subfolder in the output folder. rootDirmust be set as a common root for all project folders.

Structure outFiles (Structuring for outFiles)

outFileThe layout of compilations with is more flexible because relative paths are not very important.
One thing to remember is that until the "last" project, prependyou don't want to use - this will improve build time and reduce the number of I/O required for a given build.
The TypeScript repository itself is a good reference here - there are several "library" projects and "endpoint" projects; The "endpoint" project remains as small as possible and pulls only the libraries that you need.

Translation of JSX.md

Title: JSX
Layout: docs
permalink: /id/docs/handbook/jsx.html
oneline: Using JSX with TypeScript

translatable: true

JSX It is an embedded syntax, which is like XML.
It's meant to be converted into JavaScript. valid, although the semantics of the transformation are specific to implementation.
JSX became popular with the framework ReactBut since then it has also seen other implementations.
TypeScript supports embeding, type check, and compile JSX directly into JavaScript.

Basic Use

To use JSX, you must do the following two things:

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

TypeScript has three types of JSX modes: preserve, reactand react-native.
This mode only applies to stage, as for type checks, that doesn't apply.
Mode preserve I will maintain JSX as part of Output to be further used by other transformation steps (e.g. Babylon).
Moreover Output- it will have a file extension .jsx.
Mode react will issueReact.createElement, there is no need to go through the JSX transformation before use, and the output will have a file extension .js.
Mode react-native same with pertahankan which retains all JSX, but the result will instead have a file extension .js.

Mode Input Output Extension Output file
preserve <div /> <div /> .jsx
react <div /> React.createElement("div") .js
react-native <div /> <div /> .js

You can set this mode using flag command line --jsx or the appropriate options in the file tsconfig.json You.

*Note: You can specify a function factory JSX to be used when targeting react JSX issuer with options --jsxFactory (default value to React.createElement)

Operator as

Remember how to write type affirmations:

var foo = <foo>bar;

This confirms the variable bar have type foo.
Since TypeScript also uses square brackets for type affirmation, combining it with the JSX syntax will cause certain difficulties. As a result, TypeScript does not allow the use of square brackets for type affirmations on files. .tsx.

Because the syntax above cannot be used on files .tsx, then an alternative to type affirmation can use the operator as.
Examples can be easily rewritten with the operator. as.

var foo = bar as foo;

Operator as available in both file types, .ts and .tsx, and has the same treatment as type affirmation using elbow brackets.

Type Check

The order to be understood regarding type checking in JSX, i.e. you must first understand the difference between intrinsic elements and value-based elements. There's an expression. <expr /> and expr which may refer to something intrinsic to an environment (e.g. div or span in a DOM environment) or on custom components that you have created.
This is important for the following two reasons:

  1. For React, the intrinsic element is considered a string (React.createElement("div")The components you make are not (React.createElement(MyComponent)).
  2. The type of attribute passed to the JSX element should look different.
    Intrinsic element attributes should be known Intrinsically while the components will like to want to determine their own set of attributes.

TypeScript uses Some conventions with React to distinguish it.
Intrinsic elements always start with lowercase, and value-based elements always start with uppercase.

Intrinsic element

Intrinsic elements are sought in Interface Specifically, that is JSX.IntrinsicElements.
The standard, if Interface This is not specified, so whatever happens and the intrinsic element will not be checked for type.
However, if Interface If this exists, the name of the intrinsic element will be searched as a property in Interface JSX.IntrinsicElements.
Examples:

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

<foo />; // ok
<bar />; // galat

In the example above, <foo /> It's going to go well, but <bar /> it will cause an error, because <bar /> not specified on Interface JSX.IntrinsicElements.

Note: You can also specify indexer to get all string-type elements inside JSX.IntrinsicElements, as follows:

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

Value-Based Elements

Value-based elements will be searched by Identifier Which is in one Scope.

import MyComponent from "./myComponent";

<MyComponent />; // ok
<SomeOtherComponent />; // galat

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

  1. Function Component (FC)
  2. Class Component

Since these two types of value-based elements are indistinguishable from each other in JSX expressions, then first TS will try to complete the expression as Function Component use Overloading. If the process is successful, then TS completes the expression to its declaration. If it fails to complete as Function Component, then TS will then try to solve it as Class Component. If it fails, TS will report an error.

Function Component

As the name suggests, this component is defined using the JavaScript function where the first argument is a props object.
TS insists that the type of return must be able to be given to JSX.Element.

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>

Because Function Component Is a JavaScript function, so the overload function can be used here:

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: Function Component Previously known as Stateless Function Component (SFC). Because Function Component It can no longer be considered Stateless in the latest version of react, SFC and his aliasStatelessComponent Not used anymore.

Class Component

This makes it possible to define the type of class component.
However, to do so, it is best to understand the following two new terms: element type class and element type instance.

If there is <Expr />so type class elements be Expr.
In the example above, if MyComponent be class ES6, then type class-He is a constructor and static from class aforementioned.
If MyComponent It's a factory function, and it's a type of class-It's a function in itself.

After the class type is created, the type instance determined by the combination of return types from type construction class or call signature (Wherever there is).
So again, in the case of the ES6 class, the instance type is that type of class instance, and in the case of factory function, it will be the type of value returned from the function.

class MyComponent {
  render() {}
}

// menggunakan konstruksi signature
var myComponent = new MyComponent();

// tipe class elemen => MyComponent
// tipe instance elemen => { render: () => void }

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

// menggunakan call signature
var myComponent = MyFactoryFunction();

// tipe class elemen => FactoryFunction
// tipe instance elemen => { render: () => void }

Element type instance That's interesting, because it has to be-assign to JSX.ElementClass Or the result will be an error.
Default JSX.ElementClass be {}, but this can be added to limit the use of JSX only to the type that suits the right interface.

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

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

<MyComponent />; // ok
<MyFactoryFunction />; // ok

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

<NotAValidComponent />; // galat
<NotAValidFactoryFunction />; // galat

Attribute Type Check

The first step to checking an attribute type is to specify the type of element attribute.
It differs slightly between intrinsic and value-based elements.

For intrinsic elements, this is a type of property on JSX.IntrinsicElements

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

// tipe atribut elemen untuk 'foo' is '{bar?: boolean}'
<foo bar />;

For value-based elements, this is a little more complex.
This is determined by the type of property on instance element type which has been determined.
Which properties are used to be determined by JSX.ElementAttributesProperty.
It must be declared with one property.
The name of the property was later used.
Start TypeScript 2.8, if JSX.ElementAttributesProperty not provided, the first type of parameter of the constructor of class elements or summoning Function Component It will be used instead.

declare namespace JSX {
  interface ElementAttributesProperty {
    props; // menentukan nama properti yang akan digunakan
  }
}

class MyComponent {
  // menentukan properti pada tipe instance elemen
  props: {
    foo?: string;
  };
}

// tipe atribut elemen untuk 'MyComponent' adalah '{foo?: string}'
<MyComponent foo="bar" />;

Element attribute types are used to check attributes in JSX.
Optional and compulsory properties are supported.

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

<foo requiredProp="bar" />; // ok
<foo requiredProp="bar" optionalProp={0} />; // ok
<foo />; // galat, tidak ada requiredProp
<foo requiredProp={0} />; // galat, requiredProp seharusnya bertipe string
<foo requiredProp="bar" unknownProp />; // galat, unknownProp tidak ada
<foo requiredProp="bar" some-unknown-prop />; // ok, karena 'some-unknown-prop' bukan identifier yang valid

Note: If the attribute name is not Identifier Valid JS (such as attributes data- *), it is not considered an error if it is not found in the element attribute type.

In addition, the interface JSX.IntrinsicAttributes can be used to determine additional properties used by Framework JSX is not generally used by props or component arguments – for example key in React. Specializing further, generic types JSX.IntrinsicClassAttributes<T> It can also be used to assign the same additional attribute type only to class component (And not function component). In this type, generic parameters correspond to the type instance class. In React, this is used to allow attributes ref with type Ref <T>. In general, all properties on this interface must be optional, unless you intend to have users Framework JSX you need to provide multiple attributes on each tag.

Operator spread It also works:

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

var badProps = {};
<foo {...badProps} />; // galat

Examination Children Type

In TypeScript 2.3, TS introduces type checks to children. Children It is a special property in element attribute type where child JSXExpression taken to be incorporated into the attribute.
Similar to how to use JSX.ElementAttributesProperty To determine the name of Props, TS uses JSX.
JSX.ElementChildrenAttribute must be declared with a single property.

declare namespace JSX {
  interface ElementChildrenAttribute {
    children: {}; // menentukan nama children untuk digunakan
  }
}
<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>

You can determine the type of children Like any other attribute. This will change the standard type, for example. React typings If you use it.

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>

// Error: children adalah tipe JSX.Element, bukan array dari JSX.Element.
<Component name="bar">
  <h1>Hello World</h1>
  <h2>Hello World</h2>
</Component>

// Error: children adalah tipe JSX.Element, bukan array dari JSX.Element maupun string.
<Component name="baz">
  <h1>Hello</h1>
  World
</Component>

JSX result type

By default, the result of JSX expression is of the type any.
You can adjust the type by specifying Interface JSX.Element.
However, it is not possible to retrieve type information about elements, attributes or derivatives of JSX from Interface this.
That is black box.

Embed Expressions

JSX allows you to embed expressions between tags by flanking expressions with curly brackets ({}).

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

The code above will result in an error because you can't split String with numbers.
Output- when using the option preserve, it looks like:

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

React integration

To use JSX with React, you must use React typings. These typings define namespace JSX It's appropriate to use with React.

/// <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" />; // ok
<MyComponent foo={0} />; // galat

Factory Function

Factory function used by compiler options jsx: react configurable. It can be set using command line options jsxFactory, or comments @jsx line to set it on a per file basis. For example, if you set jsxFactory to createElement, <div /> Will do it as createElement("div") not React.createElement("div").

The preview version of the comment can be used as such (in TypeScript 2.8):

import preact = require("preact");
/* @jsx preact.h */
const x = <div />;

It will be:

const preact = require("preact");
const x = preact.h("div", null);

Factory The selected will also affect where namespace JSX searched (for type check information) before returning to Global. If factory specified as React.createElement (standard), the compiler will check React.JSX Before checking JSX Global. If factory specified as h, then he'll check. h.JSX before JSX Global.

Generated by 🚫 dangerJS against fc8c2aa

@yahma25 yahma25 marked this pull request as draft August 18, 2021 15:20
@yahma25
Copy link
Contributor Author

yahma25 commented Aug 18, 2021

🤔 action build 중 실패한 게 있어서 origin/main 으로 병합하여 최신화 했더니 이 이슈를 초과하는 변경사항까지 반영되었네요. 다시 올리겠습니다.

@yahma25 yahma25 closed this Aug 18, 2021
@yahma25 yahma25 deleted the Translation-to-ko-palyground-Structural-Typing branch August 18, 2021 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.