Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

translate "Correctness Fixes and Breaking Changes" in ko #190

Merged
merged 11 commits into from Dec 16, 2022

Conversation

JeGwan
Copy link
Contributor

@JeGwan JeGwan commented Dec 12, 2022

No description provided.

@github-actions
Copy link
Contributor

Thanks for the PR!

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

@github-actions
Copy link
Contributor

github-actions bot commented Dec 12, 2022

Translation of TypeScript 4.9.md

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

oneline: TypeScript 4.9 Release Notes

satisfies operator

TypeScript developers often face a dilemma. We have some expressions with this type and _accord_I'd like to make sure it does, but for inference, the expression of _The most specific type_There are times when you want to keep it.

For example

// 각 속성은 문자열 또는 RGB 튜플일 수 있습니다.
const palette = {
    red: [255, 0, 0],
    green: "#00ff00",
    bleu: [0, 0, 255]
//  ^^^^ sacrebleu - 오타를 냈습니다!
};

// 우리는 배열 메서드를 'red'에 사용하고 싶습니다...
const redComponent = palette.red.at(0);

// 혹은 'green'에 문자열 메서드를 사용하고 싶을 수 있습니다...
const greenNormalized = palette.green.toUpperCase();

We are bleu minister blueshould have been written.
paletteBy indicating the type in bleu You can catch typos, but if you do, you'll lose information about each attribute.

type Colors = "red" | "green" | "blue";

type RGB = [red: number, green: number, blue: number];

const palette: Record<Colors, string | RGB> = {
    red: [255, 0, 0],
    green: "#00ff00",
    bleu: [0, 0, 255]
//  ~~~~ 이제 오타를 올바르게 감지했습니다.
};

// 하지만 여기서 원치 않는 문제가 발생했습니다. 'palette.red'가 문자열이 "될 수 있다"는것 입니다.
const redComponent = palette.red.at(0);

satisfies You can use operators to verify that the type of an expression matches a specific type without changing the result type of the expression.
For example, we have satisfiesUsing the paletteAll properties of string | number[]You can verify that it is compatible with

type Colors = "red" | "green" | "blue";

type RGB = [red: number, green: number, blue: number];

const palette = {
    red: [255, 0, 0],
    green: "#00ff00",
    bleu: [0, 0, 255]
//  ~~~~ 오타가 잡혔습니다!
} satisfies Record<Colors, string | RGB>;

// 두 메서드 모두 여전히 접근할 수 있습니다!
const redComponent = palette.red.at(0);
const greenNormalized = palette.green.toUpperCase();

satisfiescan be used to detect many errors.
For example, if an object is of a certain type, all You can have the key, but not more.

type Colors = "red" | "green" | "blue";

// 'Colors' 키가 정확한지 확인합니다.
const favoriteColors = {
    "red": "yes",
    "green": false,
    "blue": "kinda",
    "platypus": false
//  ~~~~~~~~~~ 에러 - "platypus"는 'Colors' 리스트에 없습니다.
} satisfies Record<Colors, unknown>;

// 'red', 'green' 및 'blue' 속성의 모든 정보가 유지됩니다.
const g: boolean = favoriteColors.green;

Sometimes we may be more interested in the type of each attribute than in whether the attribute name matches.
In this case, you can also check whether all attribute values of the object conform to some type.

type RGB = [red: number, green: number, blue: number];

const palette = {
    red: [255, 0, 0],
    green: "#00ff00",
    blue: [0, 0]
    //    ~~~~~~ 에러!
} satisfies Record<string, string | RGB>;

// 각 속성에 대한 정보는 계속 유지됩니다.
const redComponent = palette.red.at(0);
const greenNormalized = palette.green.toUpperCase();

For more examples, Proposed issue and A pull request that implements thisCheck it out.
We have implemented this feature with Oleksandr TarasiukThank you.

Unlisted Property Narrowing with the in Operator

As developers, we often need to deal with values that aren't fully known at runtime.
In fact, we often don't know if properties exist, whether we're getting a response from a server or reading a configuration file.
JavaScript's in operator can check whether a property
exists on an object.

Previously, TypeScript allowed us to narrow away any types that don't explicitly list a property.

interface RGB {
    red: number;
    green: number;
    blue: number;
}

interface HSV {
    hue: number;
    saturation: number;
    value: number;
}

function setColor(color: RGB | HSV) {
    if ("hue" in color) {
        // 'color' now has the type HSV
    }
    // ...
}

Here, the type RGB didn't list the hue and got narrowed away, and leaving us with the type HSV.

But what about examples where no type listed a given property?
In those cases, the language didn't help us much.
Let's take the following example in JavaScript:

function tryGetPackageName(context) {
    const packageJSON = context.packageJSON;
    // Check to see if we have an object.
    if (packageJSON && typeof packageJSON === "object") {
        // Check to see if it has a string name property.
        if ("name" in packageJSON && typeof packageJSON.name === "string") {
            return packageJSON.name;
        }
    }

    return undefined;
}

Rewriting this to canonical TypeScript would just be a matter of defining and using a type for context;
however, picking a safe type like unknown for the packageJSON property would cause issues in older versions of TypeScript.

interface Context {
    packageJSON: unknown;
}

function tryGetPackageName(context: Context) {
    const packageJSON = context.packageJSON;
    // Check to see if we have an object.
    if (packageJSON && typeof packageJSON === "object") {
        // Check to see if it has a string name property.
        if ("name" in packageJSON && typeof packageJSON.name === "string") {
        //                                              ~~~~
        // error! Property 'name' does not exist on type 'object.
            return packageJSON.name;
        //                     ~~~~
        // error! Property 'name' does not exist on type 'object.
        }
    }

    return undefined;
}

This is because while the type of packageJSON was narrowed from unknown to object, the in operator strictly narrowed to types that actually defined the property being checked.
As a result, the type of packageJSON remained object.

TypeScript 4.9 makes the in operator a little bit more powerful when narrowing types that don't list the property at all.
Instead of leaving them as-is, the language will intersect their types with Record<"property-key-being-checked", unknown>.

So in our example, packageJSON will have its type narrowed from unknown to object to object & Record<"name", unknown>
That allows us to access packageJSON.name directly and narrow that independently.

interface Context {
    packageJSON: unknown;
}

function tryGetPackageName(context: Context): string | undefined {
    const packageJSON = context.packageJSON;
    // Check to see if we have an object.
    if (packageJSON && typeof packageJSON === "object") {
        // Check to see if it has a string name property.
        if ("name" in packageJSON && typeof packageJSON.name === "string") {
            // Just works!
            return packageJSON.name;
        }
    }

    return undefined;
}

TypeScript 4.9 also tightens up a few checks around how in is used, ensuring that the left side is assignable to the type string | number | symbol, and the right side is assignable to object.
This helps check that we're using valid property keys, and not accidentally checking primitives.

For more information, read the implementing pull request

Auto-Accessors in Classes

TypeScript 4.9 supports an upcoming feature in ECMAScript called auto-accessors.
Auto-accessors are declared just like properties on classes, except that they're declared with the accessor keyword.

class Person {
    accessor name: string;

    constructor(name: string) {
        this.name = name;
    }
}

Under the covers, these auto-accessors "de-sugar" to a get and set accessor with an unreachable private property.

class Person {
    #__name: string;

    get name() {
        return this.#__name;
    }
    set name(value: string) {
        this.#__name = name;
    }

    constructor(name: string) {
        this.name = name;
    }
}

You can [read up more about the auto-accessors pull request on the original PR](https://github.com/microsoft/TypeScript/pull/49705).

NaN Equivalence check

The main problem for JavaScript developers is that they use the built-in equivalent operators. NaN This is the point to check the value.

NaNis a special numeric value, which means "Not a Number".
NaNThere is no such thing as the same. Even NaNis the same.

console.log(NaN == 0)  // false
console.log(NaN === 0) // false

console.log(NaN == NaN)  // false
console.log(NaN === NaN) // false

But at least symmetrically Everything is always NaNis not the same as

console.log(NaN != 0)  // true
console.log(NaN !== 0) // true

console.log(NaN != NaN)  // true
console.log(NaN !== NaN) // true

All languages, including IEEE-754 floats, behave the same, so it's technically not just JavaScript.
The default numeric type in JavaScript is floating-point numbers, and JavaScript often uses numeric syntax as NaNCan be analyzed with:
therefore NaN Value checking is common, [Number.isNaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN) to check correctly. But as mentioned above, many people mistakenly someValue === NaNto confirm.

TypeScript is now NaN Comparing the values directly shows an error and Number.isNaN I suggest using it.

function validate(someValue: number) {
    return someValue !== NaN;
    //     ~~~~~~~~~~~~~~~~~
    // error: This condition will always return 'true'.
    //        Did you mean '!Number.isNaN(someValue)'?
}

We believe this change will go a long way toward catching newbie errors, similar to how TypeScript currently throws errors in comparisons against object and array literals.

[contributed to this feature] (https://github.com/microsoft/TypeScript/pull/50626) [Oleksandr Tarasiuk] I would like to thank (https://github.com/a-tarasyuk).

Watching Files Using File System Events

In previous versions, TypeScript used to spy on individual files. _polling_Heavily relied on.
Using a polling strategy means watching the state of files periodically for updates.
In Node.js, click [fs.watchFile](https://nodejs.org/docs/latest-v18.x/api/fs.html#fswatchfilefilename-options-listener) is a built-in way to get polling file watchers.
Polling tends to be more predictable across platforms and file systems, but you should check for file updates even when the CPU periodically hangs and nothing has changed.
If you have dozens of files, it may not make much difference.
But in a larger project with many files or node_modulesIf there are many files in the DataSet, polling can be resource-intensive.

In general, a better approach is to use file system events.
Instead of polling, it tells you that you are interested in updating a particular file, and that the file is indeed You can provide callbacks when they change.
Most modern platforms are CreateIoCompletionPort, kqueue, epoll and inotifyprovides the same functionality and API.
Node.js is mostly [fs.watch] (https://nodejs.org/docs/latest-v18.x/api/fs.html#fswatchfilename-options-listener) to abstract it.
File system events generally work fine, but if you use them and fs.watch There are [many caveats] (https://nodejs.org/docs/latest-v18.x/api/fs.html#caveats) to using the API.
Watchers must consider [inode watch](https://nodejs.org/docs/latest-v18.x/api/fs.html#inodes), [unavailability on a particular file system](https://nodejs.org/docs/latest-v18.x/api/fs.html#availability) (e.g. network file systems), whether recursive file watches are enabled, whether directory renaming triggers events, and even file watcher exhaustion!
It's not easy, especially if you're looking for a cross-platform.

As a result, we chose the lowest common denominator of polling as the base value.
This was not always the case, but in most cases.

Over time, we have provided the means to [choose a different file surveillance strategy](https://www.typescriptlang.org/docs/handbook/configuring-watch.html).
This allowed us to get feedback and strengthen our file surveillance implementation for most platform issues.
Since TypeScript needed to be extended to a larger codebase and improved in this area, we thought it would be a worthwhile investment to replace file system events with defaults.

In TypeScript 4.9, file watches are driven by file system events by default and only fall back to polling if you fail to set up an event-driven watcher.
For most developers, --watch When running in mode, or with a TypeScript-based editor such as Visual Studio or VS Code, it should provide a much less resource-intensive environment.

[The way file watches work is still based on environment variables and watchOptionscan be configured via [https://www.typescriptlang.org/docs/handbook/configuring-watch.html], and some editors, such as VS Code, watchOptionscan be supported independently.] (https://code.visualstudio.com/docs/getstarted/settings#:~:text=typescript%2etsserver%2ewatchOptions)
Developers with more unusual settings where source code resides on network file systems such as NFS and SMB may need to reselect the previous behavior. However, if your server has adequate processing power, it may be better to enable SSH and run TypeScript remotely to allow direct access to local files.
VS Code has many [remote extensions] (https://marketplace.visualstudio.com/search?term=remote&target=VSCode&category=All%20categories&sortBy=Relevance) that make this easier.

You can learn more about this change (https://github.com/microsoft/TypeScript/pull/50366) on GitHub.

"Remove Unused Imports" and "Sort Imports" Commands for Editors

Previously, TypeScript only supported two editor commands to manage imports.
For our examples, take the following code:

import { Zebra, Moose, HoneyBadger } from "./zoo";
import { foo, bar } from "./helper";

let x: Moose | HoneyBadger = foo();

The first was called "Organize Imports" which would remove unused imports, and then sort the remaining ones.
It would rewrite that file to look like this one:

import { foo } from "./helper";
import { HoneyBadger, Moose } from "./zoo";

let x: Moose | HoneyBadger = foo();

In TypeScript 4.3, we introduced a command called "Sort Imports" which would only sort imports in the file, but not remove them - and would rewrite the file like this.

import { bar, foo } from "./helper";
import { HoneyBadger, Moose, Zebra } from "./zoo";

let x: Moose | HoneyBadger = foo();

The caveat with "Sort Imports" was that in Visual Studio Code, this feature was only available as an on-save command - not as a manually triggerable command.

TypeScript 4.9 adds the other half, and now provides "Remove Unused Imports".
TypeScript will now remove unused import names and statements, but will otherwise leave the relative ordering alone.

import { Moose, HoneyBadger } from "./zoo";
import { foo } from "./helper";

let x: Moose | HoneyBadger = foo();

This feature is available to all editors that wish to use either command;
but notably, Visual Studio Code (1.73 and later) will have support built in and will surface these commands via its Command Palette.
Users who prefer to use the more granular "Remove Unused Imports" or "Sort Imports" commands should be able to reassign the "Organize Imports" key combination to them if desired.

You can [view specifics of the feature here](https://github.com/microsoft/TypeScript/pull/50931).

Go-to-Definition on return Keywords

In the editor, when running a go-to-definition on the return keyword, TypeScript will now jump you to the top of the corresponding function.
This can be helpful to get a quick sense of which function a return belongs to.

We expect TypeScript will expand this functionality to more keywords [such as await and yield](https://github.com/microsoft/TypeScript/issues/51223) or [switch, case, and default](https://github.com/microsoft/TypeScript/issues/51225).

[This feature was implemented] (https://github.com/microsoft/TypeScript/pull/51227) thanks to [Oleksandr Tarasiuk](https://github.com/a-tarasyuk).

Performance improvements

TypeScript has several small but notable performance improvements.

First, in all syntax nodes switch Use a function table lookup instead of a statement in TypeScript forEachChild The function has been refactored.
forEachChildis a working tool for traversing syntax nodes in the compiler and is heavily used in the binding phase of the compiler along with parts of language services.
forEachChild The refactoring reduced the time spent on the binding phase and across language service operations by up to 20%.

forEachChildAfter you see the performance improvements for the NodeT visitEachChildI tried refactoring in .
The same refactoring reduced the time spent generating project results by up to 3%.

forEachChild's initial exploration was inspired by [blog posts] (https://artemis.sh/2022/08/07/emulating-calculators-fast-in-js.html) by [Artemis Everfree] (https://artemis.sh/).
I have reason to believe that the root cause of the speedup is more related to feature size/complexity than the issue described in the blog post, but I'm grateful to have learned from experience and been able to try out the relatively fast refactoring that made TypeScript faster.

Finally, we've optimized the way TypeScript preserves information about types in the actual branch of conditional types.
In the following types

interface Zoo<T extends Animal> {
    // ...
}

type MakeZoo<A> = A extends Animal ? Zoo<A> : never;

TypeScript is Zoo<A>When checking if is valid ADegree AnimalYou have to "remember" that it should be.
By default, Aand AnimalIt is done by creating a special type that is used to maintain the intersection of .
However, TypeScript has worked this before, and it's not always necessary.
Also, some bad code in the type checker did not simplify these special types.
TypeScript now defers the crossing of these types until necessary.
For codebases that use conditional types heavily, you can see significant speedup with TypeScript, but the performance test suite saw a more modest 3% reduction in type checking time.

You can learn more about it in each pull request.

Corrections and changes

lib.d.ts update

TypeScript tries to avoid major breaks, but even the smallest changes to the built-in libraries can be problematic.
DOM and lib.d.ts We don't expect major breaks to happen as a result of updates, but they can often cause small problems.

Promise.resolve Better types for

present Promise.resolveto strip away the Promise-like type that is passed by this Awaited Type.
This is often more accurate Promise Type returns, but this improved type Promise minister any or unknown You can also break the existing code you were expecting a type.
For more information, see Original Change (https://github.com/microsoft/TypeScript/pull/33074).

JavaScript Export (Emit) no longer omits Import

When TypeScript first supported type checking and compilation for JavaScript, it inadvertently supported a feature called import omission.
In short, if the imported item is not used as a value or references the value at runtime, the compiler removes the import during the export process.

This behavior was particularly troubling given that TypeScript often had to trust inaccurate declaration files when detecting if import was referring to a value.
TypeScript now preserves imports within JavaScript files.

// Input:
import { someValue, SomeClass } from "some-module";

/** @type {SomeClass} */
let val = someValue;

// Previous Output:
import { someValue } from "some-module";

/** @type {SomeClass} */
let val = someValue;

// Current Output:
import { someValue, SomeClass } from "some-module";

/** @type {SomeClass} */
let val = someValue;

For more information, see Implementing Change (https://github.com/microsoft/TypeScript/pull/50404).

exportsprice typesVersionsIt has a higher priority.

Previously, TypeScript --moduleResolution node16 Conditions package.jsonWhen resolving via exports than the field typesVersions Fields took precedence.
If this change affects your library package.jsonof exports In the field types@ You can do this by adding a version selector.

  {
      "type": "module",
      "main": "./dist/main.js"
      "typesVersions": {
          "<4.8": { ".": ["4.8-types/main.d.ts"] },
          "*": { ".": ["modern-types/main.d.ts"] }
      },
      "exports": {
          ".": {
+             "types@<4.8": "4.8-types/main.d.ts",
+             "types": "modern-types/main.d.ts",
              "import": "./dist/main.js"
          }
      }
  }

For more information, see this pull request(https://github.com/microsoft/TypeScript/pull/50890).

SubstitutionTypeIn substituteprice constraintIt is replaced by

As part of the optimization of the substitution type SubstitutionType The object represents an effective substitution (typically an intersection of base type and implicit constraint) substitution It no longer includes the property. minister constraint Include only properties.

Read more in the original [pull request] (https://github.com/microsoft/TypeScript/pull/50397).

Generated by 🚫 dangerJS against b3d42b1

@JeGwan
Copy link
Contributor Author

JeGwan commented Dec 12, 2022

@microsoft-github-policy-service agree

Copy link
Contributor

@yeonjuan yeonjuan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JeGwan 고생하셨습니다. 코멘트 남깁니다.

docs/documentation/ko/release-notes/TypeScript 4.9.md Outdated Show resolved Hide resolved
docs/documentation/ko/release-notes/TypeScript 4.9.md Outdated Show resolved Hide resolved
docs/documentation/ko/release-notes/TypeScript 4.9.md Outdated Show resolved Hide resolved
docs/documentation/ko/release-notes/TypeScript 4.9.md Outdated Show resolved Hide resolved
docs/documentation/ko/release-notes/TypeScript 4.9.md Outdated Show resolved Hide resolved
JeGwan and others added 6 commits December 16, 2022 11:46
Co-authored-by: YeonJuan <yeonjuan93@naver.com>
Co-authored-by: YeonJuan <yeonjuan93@naver.com>
Co-authored-by: YeonJuan <yeonjuan93@naver.com>
Co-authored-by: YeonJuan <yeonjuan93@naver.com>
Co-authored-by: YeonJuan <yeonjuan93@naver.com>
@JeGwan
Copy link
Contributor Author

JeGwan commented Dec 16, 2022

@yeonjuan @bumkeyy
마지막에 맞춤법 검사를 한번하는걸 깜빡했네요 😅
정성 코멘트 감사합니다.

@bumkeyy
Copy link
Contributor

bumkeyy commented Dec 16, 2022

LGTM

@github-actions github-actions bot merged commit d6fd540 into microsoft:main Dec 16, 2022
@github-actions
Copy link
Contributor

Merging because @bumkeyy is a code-owner of all the changes - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants