diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d6b10dd4f4f2..c8ca28c32c10 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -41,3 +41,10 @@ packages/tsconfig-reference/copy/id/**/*.md @jefrydco @nusendra @mazipan @mandap packages/typescriptlang-org/src/copy/id/**/*.ts @jefrydco @nusendra @mazipan @mandaputtra [translation] [id] packages/typescriptlang-org/src/copy/id.ts @jefrydco @nusendra @mazipan @mandaputtra [translation] [id] packages/documentation/copy/id/**/*.md @jefrydco @nusendra @mazipan @mandaputtra [translation] [id] + +# Collaborators for Ukrainian Translation of the Website +packages/playground-examples/copy/uk @AMashoshyna [translation] [uk] +packages/tsconfig-reference/copy/uk/**/*.md @AMashoshyna [translation] [uk] +packages/typescriptlang-org/src/copy/uk/**/*.ts @AMashoshyna [translation] [uk] +packages/typescriptlang-org/src/copy/uk.ts @AMashoshyna [translation] [uk] +packages/documentation/copy/uk/**/*.md @AMashoshyna [translation] [uk] diff --git a/.github/workflows/CI-post.yml b/.github/workflows/CI-post.yml deleted file mode 100644 index 006420aab674..000000000000 --- a/.github/workflows/CI-post.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: Post CI Secure Run -on: - workflow_run: - workflows: ["CI"] - types: - - completed - -jobs: - playground: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: "13.x" - - # Cache yarn deps, to speed up CI - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn config get cacheFolder)" - - - uses: actions/cache@v1 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - # Install, should be basically be instant if cached - - run: yarn install - env: - YARN_CHECKSUM_BEHAVIOR: ignore - - run: mkdir built - - - name: Download artifact - uses: dawidd6/action-download-artifact@v2 - with: - workflow: CI.yml - commit: ${{ github.event.workflow_run.head_commit.id }} - name: built-site - path: built/public - - - name: "Make a fake 'app' for the azure project of the static HTML" - run: | - echo '{ "name": "fake", "scripts": { "build": "" } }' > built/package.json - - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" - - - name: "Change branch to one specific to this PR, as that's what the SWA uploader uses to determine env" - run: | - git checkout -b pr_${{ github.event.workflow_run.pull_requests[0].number }} - - - name: Build And Deploy - uses: Azure/static-web-apps-deploy@v0.0.1-preview - id: deploy - with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_MEADOW_0C9756810 }} - repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments) - action: "upload" - ###### Repository/Build Configurations - These values can be configured to match you app requirements. ###### - # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "built" # App source code path - app_artifact_location: "public" # Subfolder in built - ###### End of Repository/Build Configurations ##### - - - run: "yarn workspace typescriptlang-org create-lighthouse-json" - env: - PR_DEPLOY_URL_ROOT: ${{ steps.deploy.outputs.static_web_app_url }} - - # danger for PR builds - - run: "yarn danger ci" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_DEPLOY_URL_ROOT: ${{ steps.deploy.outputs.static_web_app_url }} diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d65f9b977010..d36e448fb457 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -41,6 +41,30 @@ jobs: - run: yarn bootstrap - run: yarn workspace typescriptlang-org build + # Blocked on https://github.com/Azure/static-web-apps/issues/147 + # + + # PR deploys via static web apps + # - name: "Make a fake 'app' for the azure project of the static HTML" + # run: | + # mkdir fakeapp + # mv packages/typescriptlang-org/public fakeapp/public + # ls fakeapp + # ls fakeapp/public + # echo '{ "name": "fake", "scripts": { "build": "" } }' > fakeapp/package.json + + # - name: Build And Deploy + # id: builddeploy + # uses: Azure/static-web-apps-deploy@v0.0.1-preview + # if: github.event.base.repo.id == github.event.head.repo.id + # with: + # azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_MEADOW_0C9756810 }} + # repo_token: ${{ secrets.GITHUB_TOKEN }} + # action: "upload" + # app_location: "fakeapp" + # api_location: "api" + # app_artifact_location: "public" + # Verify it compiles - run: yarn compile # Run all the package's tests @@ -51,40 +75,23 @@ jobs: - name: "Validates that TypeScript plugins work" run: npm init typescript-playground-plugin playground-my-plugin - - name: "Copy PR JSON" - run: cp $GITHUB_EVENT_PATH ${{ github.workspace }}/packages/typescriptlang-org/public/pr.json - - - uses: actions/upload-artifact@v2 - with: - name: built-site - path: ${{ github.workspace }}/packages/typescriptlang-org/public/**/* - - windows: - runs-on: windows-latest - - steps: - # Check out, and set up the node infra - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: "13.x" - - # Cache yarn deps, to speed up CI - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn config get cacheFolder)" - - - uses: actions/cache@v1 - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - # Get local dependencies - - run: yarn install + # danger for PR builds + - if: github.event_name == 'pull_request' && github.event.base.repo.id == github.event.head.repo.id + run: "yarn danger ci" env: - YARN_CHECKSUM_BEHAVIOR: ignore - - - run: yarn bootstrap - - run: yarn build + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_DEPLOY_URL_ROOT: ${{ steps.deploy.outputs.static_web_app_url }} + # + # Blocked on https://github.com/Azure/static-web-apps/issues/147 + # + # close_pull_request_job: + # if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.base.repo.id == github.event.head.repo.id + # runs-on: ubuntu-latest + # name: Close Pull Request Job + # steps: + # - name: Close Pull Request + # id: closepullrequest + # uses: Azure/static-web-apps-deploy@v0.0.1-preview + # with: + # azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_MEADOW_0C9756810 }} + # action: "close" diff --git a/.github/workflows/PR-closed-post.yml b/.github/workflows/PR-closed-post.yml deleted file mode 100644 index f7814172be67..000000000000 --- a/.github/workflows/PR-closed-post.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Post CI Secure Run -on: - workflow_run: - workflows: ["Closed PR"] - types: - - completed - -jobs: - playground: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: "Change branch to one specific to this PR, as that's what the SWA close-r uses to determine env" - run: | - git checkout -b pr_${{ github.event.workflow_run.pull_requests.[0].number }} - - - name: Close Pull Request - id: closepullrequest - uses: Azure/static-web-apps-deploy@v0.0.1-preview - with: - azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_MEADOW_0C9756810 }} - action: "close" diff --git a/.github/workflows/PR-closed.yml b/.github/workflows/PR-closed.yml deleted file mode 100644 index 1620d6a6af8b..000000000000 --- a/.github/workflows/PR-closed.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Closed PR -on: - pull_request: - types: - - closed - -jobs: - playground: - runs-on: ubuntu-latest - steps: - - run: "echo 'NOOP'" diff --git a/.github/workflows/v2-merged-staging.yml b/.github/workflows/v2-merged-staging.yml index 79b2322bce51..798f82152e3e 100644 --- a/.github/workflows/v2-merged-staging.yml +++ b/.github/workflows/v2-merged-staging.yml @@ -33,6 +33,7 @@ jobs: cp -r packages/typescriptlang-org/public site env: YARN_CHECKSUM_BEHAVIOR: ignore + TYPESCRIPT_SITE_STAGING: true - name: Deploy + Publish to CDN # You can find these keys here: diff --git a/README.md b/README.md index 37b2309036ab..7ade08f16b02 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,15 @@ yarn start Working on this repo is done by running `yarn start` - this starts up the website on port `8000` and creates a builder worker for every package in the repo, so if you make a change outside of the site it will compile and lint etc. -Some useful knowledge: +Some useful knowledge you need to know: - All packages have: `yarn build` and `yarn test` - All packages use [debug](https://www.npmjs.com/package/debug) - which means you can do `env DEBUG="*" yarn test` to get verbose logs You can manually via GH Actions for [production here](https://github.com/microsoft/TypeScript-Website/actions?query=workflow%3A%22Monday+Website+Push+To+Production%22) and [staging here](https://github.com/microsoft/TypeScript-Website/actions?query=workflow%3A%22Build+Website+To+Staging%22). +Having issues getting set up? [Consult the troubleshooting](./docs/Setup%20Troubleshooting.md). + ## Deployment Deployment is automatic: @@ -39,9 +41,14 @@ Deployment is automatic: You can find the build logs in [GitHub Actions](https://github.com/microsoft/TypeScript-Website/actions) -## Overview +## Docs + +If you want to know _in-depth_ how this website works, there is an [hour long video covering the codebase, deployment and tooling on YouTube.](https://www.youtube.com/watch?v=HOvivt6B7hE). Otherwise there are some short guides: -If you want to know _in-depth_ how this website works, there is an [hour long video covering the codebase, deployment and tooling on YouTube.](https://www.youtube.com/watch?v=HOvivt6B7hE). +- [Converting Twoslash Code Samples](./docs/Converting%20Twoslash%20Code%20Samples.md) +- [How i8n Works For Site Copy](./docs/How%20i8n%20Works%20For%20Site%20Copy.md) +- [Updating the TypeScript Version](./docs/New%20TypeScript%20Version.md) +- [Something Went Wrong](./docs/Something%20Went%20Wrong.md) # Website Packages @@ -95,7 +102,7 @@ The docs for TypeScript. Originally ported over from [microsoft/TypeScript-Handb ## Playground Examples -The code samples used in the Playground split across many languages +The code samples used in the Playground split across many languages. # Infra Packages @@ -119,7 +126,7 @@ Generates an epub file from the handbook files. You can try downloading it at ht ## Community Meta -Generates contributions JSON metadata on who edited handbook pages +Generates contributions JSON metadata on who edited handbook pages. # Contributing diff --git a/dangerfile.ts b/dangerfile.ts index 74c9bfcc33ea..88daad0142d3 100644 --- a/dangerfile.ts +++ b/dangerfile.ts @@ -2,68 +2,39 @@ // yarn danger pr https://github.com/microsoft/TypeScript-Website/pull/115 import { danger, message, markdown } from "danger" -// import { basename } from "path" -// import spellcheck from "danger-plugin-spellcheck" +import { basename } from "path" +import spellcheck from "danger-plugin-spellcheck" + +// Blocked on PR deploys, see CI.yml // import lighthouse from "danger-plugin-lighthouse" -import { readFileSync } from "fs" // Spell check all the things -// spellcheck({ settings: "artsy/peril-settings@spellcheck.json" }) - -export default () => { - // JSON reference: https://github.com/haya14busa/github-actions-playground/runs/987846369 - const contextText = readFileSync("built/public/pr.json", "utf8") - console.log(contextText) - const context = JSON.parse(contextText) - - const repo = { owner: context.event.repository.owner.login, repo: context.event.repository.name } - const prNumber = context.event.workflow_run.pull_requests[0].number - console.log(repo) - - console.log(process.env.PR_DEPLOY_URL_ROOT) - - const changedFiles = getChangedFiles(prNumber) - console.log(changedFiles) - - // Print out the PR url - const deployURL = process.env.PR_DEPLOY_URL_ROOT - message( - `Deployed to [a PR branch](${deployURL}) - [playground](${deployURL}/play) [tsconfig](${deployURL}/tsconfig) [old handbook](${deployURL}/docs/handbook/integrating-with-build-tools.html)` - ) +spellcheck({ settings: "artsy/peril-settings@spellcheck.json" }) - // lighthouse() +const deployURL = process.env.PR_DEPLOY_URL_ROOT +if (deployURL) { + const msg = `Deployed to [a PR branch](${deployURL}) - [playground](${deployURL}/play) [tsconfig](${deployURL}/tsconfig) [old handbook](${deployURL}/docs/handbook/integrating-with-build-tools.html)` + message(msg) } -const getChangedFiles = async (prNumber: number) => { - const repo = { owner: "microsoft", name: "TypeScript-website" } +// Look for new snapshots and show in a HTML table +const snapshots = danger.git.fileMatch("packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/*.png") +if (snapshots.modified) { + const oldSha = danger.github.pr.base.sha + const newSha = danger.github.pr.head.sha - // https://developer.github.com/v3/pulls/#list-pull-requests-files - const options = danger.github.api.pulls.listFiles.endpoint.merge({ ...repo, pull_number: prNumber }) + const tables = snapshots.getKeyedPaths().modified.map(p => { + const oldURL = `https://raw.githubusercontent.com/microsoft/TypeScript-Website/${oldSha}/${p}` + const newURL = `https://raw.githubusercontent.com/microsoft/TypeScript-Website/${newSha}/${p}` - /** @type { import("@octokit/rest").PullsListFilesResponseItem[]} */ - const files = await danger.github.api.paginate(options) - const fileStrings = files.map(f => `/${f.filename}`) - return fileStrings -} - -// // Look for new snapshots and show in a HTML table -// const snapshots = danger.git.fileMatch("packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/*.png") -// if (snapshots.modified) { -// const oldSha = danger.github.pr.base.sha -// const newSha = danger.github.pr.head.sha - -// const tables = snapshots.getKeyedPaths().modified.map(p => { -// const oldURL = `https://raw.githubusercontent.com/microsoft/TypeScript-Website/${oldSha}/${p}` -// const newURL = `https://raw.githubusercontent.com/microsoft/TypeScript-Website/${newSha}/${p}` + return ` +###### \`${basename(p)}\` -// return ` -// ###### \`${basename(p)}\` +Before | After +:-------------------------:|:-------------------------: +![](${oldURL}) | ![](${newURL}) +` + }) -// Before | After -// :-------------------------:|:-------------------------: -// ![](${oldURL}) | ![](${newURL}) -// ` -// }) - -// markdown(`## Snapshots updated\n\n ${tables.join("\n\n")}`) -// } + markdown(`## Snapshots updated\n\n ${tables.join("\n\n")}`) +} diff --git a/docs/New TypeScript Version.md b/docs/New TypeScript Version.md index d3e8e97d7b57..9011637847d4 100644 --- a/docs/New TypeScript Version.md +++ b/docs/New TypeScript Version.md @@ -37,6 +37,21 @@ Then run `yarn install`. That will update all of the site to use 3.9.0 for building. Run `yarn build` to see if any of the website's code broke. +##### New Handbook Docs + +You might have a new reference doc to add, they live in [`packages/documentation/copy`](https://github.com/microsoft/TypeScript-website/blob/v2/packages/documentation/copy). You can ignore languages other than `en`. The folder structure is only for your reference and has no bearing on the site navigation. Each markdown document needs a header like: + +```md +--- +title: Basic Types +layout: docs +permalink: /docs/handbook/basic-types.html +oneline: "Step one in learning TypeScript: The basic types." +--- +``` + +Or the site will fail the build. Once that file is ready, add it to the sidebar via the file [`packages/documentation/scripts/generateDocsNavigationPerLanguage.js`](https://github.com/microsoft/TypeScript-website/blob/v2/packages/documentation/scripts/generateDocsNavigationPerLanguage.js). + ##### TSConfig Reference Updating the version of TypeScript will force you to update the TSConfig Reference. It will fail incrementally with each missing compiler flag. diff --git a/docs/Setup Troubleshooting.md b/docs/Setup Troubleshooting.md new file mode 100644 index 000000000000..842fe6972e75 --- /dev/null +++ b/docs/Setup Troubleshooting.md @@ -0,0 +1,17 @@ +## Getting this Repo Set Up Troubleshooting + +#### Module `x` is not built + +Sometimes, and it's not been tracked down exactly, some dependencies of the site aren't built even though it says they are. In those cases, re-run `yarn bootstrap` and `yarn build` to re-build all the internal site deps. + +#### No syntax highlighting + +By default the website runs without twoslash code samples being evaluated, this affects the syntax highlighting. To turn it on, use `yarn start-twoslash` instead of `yarn start`. + +#### Windows + Watchman + +The Windows support for watchman is a bit meh. It's not likely to get better, given how well WSL works now. So, you _could_ use WSL to work around that. + +Though, for _a lot_ of changes to the site: Watchman is optional. All the watchman script does is run `yarn workspace [xxyy] build` when you save in a package which is not `typescriptlang-org` (the gatsby website). + +To run the site without watchman, use `yarn workspace typescriptlang-org start`. diff --git a/docs/Something Went Wrong.md b/docs/Something Went Wrong.md index 066f899e94c7..b3ffd37c032f 100644 --- a/docs/Something Went Wrong.md +++ b/docs/Something Went Wrong.md @@ -18,15 +18,13 @@ We're currently running on App Service, the places where you can find info: ### Deployment -The build to deploy train looks like this: +The build to deploy train normally looks like this: -- `v2` branch gets pushed -- pushes trigger a deploy to `SITE-STAGING` via GH Actions -- Azure picks up pushes to SITE-STAGING to deploy to the site +- `v2` branch gets pushed: +- A deploy is made to azure blob storage via [`.github/workflows/v2-merged-staging.yml`](https://github.com/microsoft/TypeScript-website/blob/v2/.github/workflows/v2-merged-staging.yml) +- Every Monday, a deploy is made from v2 to the production app via [`.github/workflows/deploy-prod.yml`](https://github.com/microsoft/TypeScript-website/blob/v2/.github/workflows/deploy-prod.yml) -We deploy by pushing to the branches [`SITE-STAGING`](https://github.com/microsoft/TypeScript-Website/tree/SITE-STAGING/) and [`SITE-PRODUCTION`](https://github.com/microsoft/TypeScript-Website/tree/SITE-PRODUCTION/) - they should show you exactly what files exist in the deploy - -You can push directly to those branches from your local computer if you have a very specific fix +You can deploy `v2` to production anytime via the ["Run workflow" button here](https://github.com/microsoft/TypeScript-Website/actions?query=workflow%3A%22Monday+Website+Push+To+Production%22), so if you have an emergency commit - it goes to `v2` then you can run the action. App Service apps are configured by [`Web.config`](https://github.com/microsoft/TypeScript-website/blob/92a9585d033e7cf802fae14v22baa73250fd610266/packages/typescriptlang-org/static/Web.config). [Here's a reference on the format](https://hangouts.google.com/call/H553wrJ9d97l2LMpNh9hAEEE). I've seen files (`*.json` & `*.manifest`) be 404s on the site because they were not in the config. diff --git a/packages/documentation/copy/en/declaration-files/Introduction.md b/packages/documentation/copy/en/declaration-files/Introduction.md index 27a85def37f4..af37526ef7d4 100644 --- a/packages/documentation/copy/en/declaration-files/Introduction.md +++ b/packages/documentation/copy/en/declaration-files/Introduction.md @@ -7,7 +7,7 @@ oneline: "How to write a high-quality TypeScript Declaration (d.ts) file" The Declaration Files section is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume basic familiarity with the TypeScript language in order to get started. -If you haven't already, you should read the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/basic-types.html) +If you haven't already, you should read the [TypeScript Handbook](/docs/handbook/basic-types.html) to familiarize yourself with basic concepts, especially types and modules. The most common case for learning how .d.ts files work is that you're typing an npm package with no types. @@ -33,15 +33,15 @@ when writing a new file. If you already know what your structure is, see the d.t ## [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html) Many common mistakes in declaration files can be easily avoided. -The [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html) section identifies common errors, -describes how to detect them, +The [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html) section identifies common errors, +describes how to detect them, and how to fix them. Everyone should read this section to help themselves avoid common mistakes. ## [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) -For seasoned authors interested in the underlying mechanics of how declaration files work, -the [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) section explains many advanced concepts in declaration writing, +For seasoned authors interested in the underlying mechanics of how declaration files work, +the [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) section explains many advanced concepts in declaration writing, and shows how to leverage these concepts to create cleaner and more intuitive declaration files. ## [Publish to npm](/docs/handbook/declaration-files/publishing.html) diff --git a/packages/documentation/copy/en/get-started/TS for JS Programmers.md b/packages/documentation/copy/en/get-started/TS for JS Programmers.md index 199403e051a9..030d2341133f 100644 --- a/packages/documentation/copy/en/get-started/TS for JS Programmers.md +++ b/packages/documentation/copy/en/get-started/TS for JS Programmers.md @@ -118,7 +118,7 @@ function deleteUser(user: User) { } ``` -There are already a small set of primitive types available in JavaScript: `boolean`, `bigint`, `null`, `number`, `string`, `symbol`, `object`, and `undefined`, which you can use in an interface. TypeScript extends this list with a few more, such as `any` (allow anything), [`unknown`](/en/play#example/unknown-and-never) (ensure someone using this type declares what the type is), [`never`](/en/play#example/unknown-and-never) (it's not possible that this type could happen), and `void` (a function which returns `undefined` or has no return value). +There are already a small set of primitive types available in JavaScript: `boolean`, `bigint`, `null`, `number`, `string`, `symbol`, `object`, and `undefined`, which you can use in an interface. TypeScript extends this list with a few more, such as `any` (allow anything), [`unknown`](/play#example/unknown-and-never) (ensure someone using this type declares what the type is), [`never`](/play#example/unknown-and-never) (it's not possible that this type could happen), and `void` (a function which returns `undefined` or has no return value). You'll see that there are two syntaxes for building types: [Interfaces and Types](/play/?e=83#example/types-vs-interfaces). You should prefer `interface`. Use `type` when you need specific features. diff --git a/packages/documentation/copy/en/handbook-v1/Interfaces.md b/packages/documentation/copy/en/handbook-v1/Interfaces.md index baf3eab63287..3b2de67ea513 100644 --- a/packages/documentation/copy/en/handbook-v1/Interfaces.md +++ b/packages/documentation/copy/en/handbook-v1/Interfaces.md @@ -254,10 +254,10 @@ The above workaround will work as long as you have a common property between `sq In this example, it was the property `width`. It will however, fail if the variable does not have any common object property. For example: ```ts twoslash +// @errors: 2559 interface SquareConfig { color?: string; width?: number; - [propName: string]: any; } function createSquare(config: SquareConfig): { color: string; area: number } { diff --git a/packages/documentation/copy/en/handbook-v1/Unions and Intersections.md b/packages/documentation/copy/en/handbook-v1/Unions and Intersections.md index c50e28a94ea2..b14ef22a4587 100644 --- a/packages/documentation/copy/en/handbook-v1/Unions and Intersections.md +++ b/packages/documentation/copy/en/handbook-v1/Unions and Intersections.md @@ -373,7 +373,7 @@ This allows you to add together existing types to get a single type that has all For example, `Person & Serializable & Loggable` is a type which is all of `Person` _and_ `Serializable` _and_ `Loggable`. That means an object of this type will have all members of all three types. -For example, if you had networking requests with consistent error handling then you could separate out the error handling into it's own type which is merged with types which correspond to a single response type. +For example, if you had networking requests with consistent error handling then you could separate out the error handling into its own type which is merged with types which correspond to a single response type. ```ts twoslash interface ErrorHandling { diff --git a/packages/documentation/copy/en/handbook-v2/Basics.md b/packages/documentation/copy/en/handbook-v2/Basics.md index 0119f97d22dd..3df34fa0827b 100644 --- a/packages/documentation/copy/en/handbook-v2/Basics.md +++ b/packages/documentation/copy/en/handbook-v2/Basics.md @@ -388,7 +388,7 @@ greet("Maddison", new Date()); ``` > While the default target is ES3, the great majority of current browsers support ES5. -> Most developers can therefore safely specify ES5 or even ES2016 as a target, unless compatibility with certain ancient browers is important. +> Most developers can therefore safely specify ES5 or even ES2016 as a target, unless compatibility with certain ancient browsers is important. ## Strictness diff --git a/packages/documentation/copy/en/handbook-v2/Object Types.md b/packages/documentation/copy/en/handbook-v2/Object Types.md index 699dc4f78f8b..f251df213f14 100644 --- a/packages/documentation/copy/en/handbook-v2/Object Types.md +++ b/packages/documentation/copy/en/handbook-v2/Object Types.md @@ -180,6 +180,7 @@ Now `xPos` and `yPos` are both definitely present within the body of `paintShape ```ts twoslash // @noImplicitAny: false @@ -196,8 +197,6 @@ function foo({ shape: Shape, xPos: number = 100 /*...*/ }) { In an object destructuring pattern, `shape: Shape` means "grab the property `shape` and redefine it locally as a variable named `Shape`. Likewise `xPos: number` creates a variable named `number` whose value is based on the parameter's `xPos`. - - ### `readonly` Properties Properties can also be marked as `readonly` for TypeScript. @@ -491,7 +490,6 @@ When TypeScript sees `Box`, it will replace every instance of `T` in `Bo In other words, `Box` and our earlier `StringBox` work identically. ```ts twoslash -// @errors: 2532 interface Box { contents: T; } @@ -500,7 +498,12 @@ interface StringBox { } let boxA: Box = { contents: "hello" }; +boxA.contents; +// ^? + let boxB: StringBox = { contents: "world" }; +boxB.contents; +// ^? ``` `Box` is reusable in that `T` can be substituted with anything, and that means that when we need a box for a new type, we don't need to declare a new box type at all (though we certainly could if we wanted to). @@ -531,7 +534,7 @@ function setContents(box: Box, newContents: T) { } ``` -At this point, it's also worth calling out that type aliases can also be generic, and we could have defined our new `Box` interface +At this point, it's also worth calling out that type aliases can also be generic, and we could have defined our new `Box` interface which was: ```ts twoslash interface Box { @@ -758,7 +761,7 @@ function setCoordinate(coord: Either2dOr3d) { // ^? console.log(`Provided coordinates had ${coord.length} dimensions`); - // ^? + // ^? } ``` diff --git a/packages/documentation/copy/en/javascript/JSDoc Reference.md b/packages/documentation/copy/en/javascript/JSDoc Reference.md index 6e2054b1754d..39bd8a4daf5c 100644 --- a/packages/documentation/copy/en/javascript/JSDoc Reference.md +++ b/packages/documentation/copy/en/javascript/JSDoc Reference.md @@ -24,7 +24,7 @@ Note any tags which are not explicitly listed below (such as `@async`) are not y #### `class` extensions -- [Property Modifiers](#jsdoc-property-modifiers) +- [Property Modifiers](#jsdoc-property-modifiers) `@public`, `@private`, `@protected`, `@readonly` The meaning is usually the same, or a superset, of the meaning of the tag given at [jsdoc.app](https://jsdoc.app). The code below describes the differences and gives some example usage of each tag. @@ -638,7 +638,6 @@ The following tags have open issues to support them: - `@const` ([issue #19672](https://github.com/Microsoft/TypeScript/issues/19672)) - `@inheritdoc` ([issue #23215](https://github.com/Microsoft/TypeScript/issues/23215)) - `@memberof` ([issue #7237](https://github.com/Microsoft/TypeScript/issues/7237)) -- `@readonly` ([issue #17233](https://github.com/Microsoft/TypeScript/issues/17233)) - `@yields` ([issue #23857](https://github.com/Microsoft/TypeScript/issues/23857)) - `{@link …}` ([issue #35524](https://github.com/Microsoft/TypeScript/issues/35524)) diff --git a/packages/documentation/copy/en/project-config/Compiler Options.md b/packages/documentation/copy/en/project-config/Compiler Options.md index 69b1ea7224f0..0d714606842e 100644 --- a/packages/documentation/copy/en/project-config/Compiler Options.md +++ b/packages/documentation/copy/en/project-config/Compiler Options.md @@ -1,8 +1,8 @@ --- -title: Compiler Options +title: tsc CLI Options layout: docs permalink: /docs/handbook/compiler-options.html -oneline: A very high-level overview of the compiler options in TypeScript +oneline: A very high-level overview of the CLI compiler options for tsc disable_toc: true --- @@ -96,7 +96,7 @@ Option | Type | Default `--outDir` | `string` | | Redirect output structure to the directory. `--outFile` | `string` | | Concatenate and emit output to single file. The order of concatenation is determined by the list of files passed to the compiler on the command line along with triple-slash references and imports. See [output file order documentation](https://github.com/Microsoft/TypeScript/wiki/FAQ#how-do-i-control-file-ordering-in-combined-output---out) for more details. `paths`[2] | `Object` | | List of path mapping entries for module names to locations relative to the `baseUrl`. See [Module Resolution documentation](/docs/handbook/module-resolution.html#path-mapping) for more details. -`--preserveConstEnums` | `boolean` | `false` | Do not erase const enum declarations in generated code. See [const enums documentation](https://www.typescriptlang.org/docs/handbook/enums.html#const-enums) for more details. +`--preserveConstEnums` | `boolean` | `false` | Do not erase const enum declarations in generated code. See [const enums documentation](/docs/handbook/enums.html#const-enums) for more details. `--preserveSymlinks` | `boolean` | `false` | Do not resolve symlinks to their real path; treat a symlinked file like a real one. `--preserveWatchOutput` | `boolean` | `false` | Keep outdated console output in watch mode instead of clearing the screen `--pretty` | `boolean` | `true` unless piping to another program or redirecting output to a file | Stylize errors and messages using color and context. @@ -132,6 +132,7 @@ Option | Type | Default ## Related -- Setting compiler options in [`tsconfig.json`](/docs/handbook/tsconfig-json.html) files. -- Setting compiler options in [MSBuild projects](/docs/handbook/compiler-options-in-msbuild.html). -- There's also the [TSConfig Reference](/tsconfig). +- Every option is fully explained in the [TSConfig Reference](/tsconfig). +- Learn how to use a [`tsconfig.json`](/docs/handbook/tsconfig-json.html) files. +- Learn how to work in an [MSBuild project](/docs/handbook/compiler-options-in-msbuild.html). + diff --git a/packages/documentation/copy/en/project-config/Project References.md b/packages/documentation/copy/en/project-config/Project References.md index 44753b0eefda..7f2c00bfded1 100644 --- a/packages/documentation/copy/en/project-config/Project References.md +++ b/packages/documentation/copy/en/project-config/Project References.md @@ -189,7 +189,7 @@ If your solution is like this, you can continue to use `msbuild` with `tsc -p` a ## Overall Structure -With more `tsconfig.json` files, you'll usually want to use [Configuration file inheritance](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) to centralize your common compiler options. +With more `tsconfig.json` files, you'll usually want to use [Configuration file inheritance](/docs/handbook/tsconfig-json.html) to centralize your common compiler options. This way you can change a setting in one file rather than having to edit multiple files. Another good practice is to have a "solution" `tsconfig.json` file that simply has `references` to all of your leaf-node projects and sets `files` to an empty array (otherwise the solution file will cause double compilation of files). Note that starting with 3.0, it is no longer an error to have an empty `files` array if you have at least one `reference` in a `tsconfig.json` file. diff --git a/packages/documentation/copy/en/project-config/tsconfig.json.md b/packages/documentation/copy/en/project-config/tsconfig.json.md index fc96ff6eb9a2..44f3cd413a32 100644 --- a/packages/documentation/copy/en/project-config/tsconfig.json.md +++ b/packages/documentation/copy/en/project-config/tsconfig.json.md @@ -1,5 +1,5 @@ --- -title: tsconfig.json +title: What is a tsconfig.json layout: docs permalink: /docs/handbook/tsconfig-json.html oneline: Learn about how a TSConfig works diff --git a/packages/documentation/copy/en/reference/Advanced Types.md b/packages/documentation/copy/en/reference/Advanced Types.md index 18c7a696cef2..2548af160d3a 100644 --- a/packages/documentation/copy/en/reference/Advanced Types.md +++ b/packages/documentation/copy/en/reference/Advanced Types.md @@ -228,8 +228,8 @@ You can include them explicitly using a union type: ```ts twoslash // @errors: 2322 -let examapleString = "foo"; -examapleString = null; +let exampleString = "foo"; +exampleString = null; let stringOrNull: string | null = "bar"; stringOrNull = null; diff --git a/packages/documentation/copy/en/reference/Declaration Merging.md b/packages/documentation/copy/en/reference/Declaration Merging.md index a1e85499226e..fedab5de4f24 100644 --- a/packages/documentation/copy/en/reference/Declaration Merging.md +++ b/packages/documentation/copy/en/reference/Declaration Merging.md @@ -202,7 +202,7 @@ namespace Album { } ``` -The visibility rules for merged members is the same as described in the 'Merging Namespaces' section, so we must export the `AlbumLabel` class for the merged class to see it. +The visibility rules for merged members is the same as described in the [Merging Namespaces](./declaration-merging.html#merging-namespaces) section, so we must export the `AlbumLabel` class for the merged class to see it. The end result is a class managed inside of another class. You can also use namespaces to add more static members to an existing class. diff --git a/packages/documentation/copy/en/reference/Iterators and Generators.md b/packages/documentation/copy/en/reference/Iterators and Generators.md index 00f94705a11d..9447366dd0f8 100644 --- a/packages/documentation/copy/en/reference/Iterators and Generators.md +++ b/packages/documentation/copy/en/reference/Iterators and Generators.md @@ -8,7 +8,7 @@ translatable: true ## Iterables -An object is deemed iterable if it has an implementation for the [`Symbol.iterator`](Symbols.md#symboliterator) property. +An object is deemed iterable if it has an implementation for the [`Symbol.iterator`](Symbols.html#symboliterator) property. Some built-in types like `Array`, `Map`, `Set`, `String`, `Int32Array`, `Uint32Array`, etc. have their `Symbol.iterator` property already implemented. `Symbol.iterator` function on an object is responsible for returning the list of values to iterate on. diff --git a/packages/documentation/copy/en/reference/Mixins.md b/packages/documentation/copy/en/reference/Mixins.md index d640d6788301..a40f6eaee027 100644 --- a/packages/documentation/copy/en/reference/Mixins.md +++ b/packages/documentation/copy/en/reference/Mixins.md @@ -246,7 +246,7 @@ playerTwo.shouldFreeze; #### Static Property Mixins [`#17829`](https://github.com/microsoft/TypeScript/issues/17829) -More of a gotcha then a constraint. +More of a gotcha than a constraint. The class expression pattern creates singletons, so they can't be mapped at the type system to support different variable types. You can work around this by using functions to return your classes which differ based on a generic: diff --git a/packages/documentation/copy/en/release-notes/Overview.md b/packages/documentation/copy/en/release-notes/Overview.md index ad0596c8a8c9..5be35935844c 100644 --- a/packages/documentation/copy/en/release-notes/Overview.md +++ b/packages/documentation/copy/en/release-notes/Overview.md @@ -4996,7 +4996,7 @@ The watcher logic has been completely rewritten to respond faster to change even ## Write-only references now flagged as unused -TypeScript 2.6 adds revised implementation the `--noUnusedLocals` and `--noUnusedParameters` [compiler options](https://www.typescriptlang.org/docs/handbook/compiler-options.html). +TypeScript 2.6 adds revised implementation the `--noUnusedLocals` and `--noUnusedParameters` [compiler options](/docs/handbook/compiler-options.html). Declarations are only written to but never read from are now flagged as unused. #### Example diff --git a/packages/documentation/copy/en/release-notes/TypeScript 2.6.md b/packages/documentation/copy/en/release-notes/TypeScript 2.6.md index 8fc6216635e6..04c22cfee736 100644 --- a/packages/documentation/copy/en/release-notes/TypeScript 2.6.md +++ b/packages/documentation/copy/en/release-notes/TypeScript 2.6.md @@ -242,7 +242,7 @@ The watcher logic has been completely rewritten to respond faster to change even ## Write-only references now flagged as unused -TypeScript 2.6 adds revised implementation the `--noUnusedLocals` and `--noUnusedParameters` [compiler options](https://www.typescriptlang.org/docs/handbook/compiler-options.html). +TypeScript 2.6 adds revised implementation the `--noUnusedLocals` and `--noUnusedParameters` [compiler options](/docs/handbook/compiler-options.html). Declarations are only written to but never read from are now flagged as unused. ##### Example diff --git a/packages/documentation/copy/en/release-notes/TypeScript 3.0.md b/packages/documentation/copy/en/release-notes/TypeScript 3.0.md index 8477bab3c4ab..3ace86928f0b 100644 --- a/packages/documentation/copy/en/release-notes/TypeScript 3.0.md +++ b/packages/documentation/copy/en/release-notes/TypeScript 3.0.md @@ -11,7 +11,7 @@ TypeScript 3.0 introduces a new concept of project references. Project reference TypeScript 3.0 also introduces a new mode for tsc, the `--build` flag, that works hand-in-hand with project references to enable faster TypeScript builds. -See [Project References handbook page](../Project%20References.md) for more documentation. +See [Project References handbook page](/docs/handbook/project-references.html) for more documentation. ## Tuples in rest parameters and spread expressions diff --git a/packages/documentation/copy/en/tutorials/Migrating from JavaScript.md b/packages/documentation/copy/en/tutorials/Migrating from JavaScript.md index 41825868b17c..b8c9a96cf820 100644 --- a/packages/documentation/copy/en/tutorials/Migrating from JavaScript.md +++ b/packages/documentation/copy/en/tutorials/Migrating from JavaScript.md @@ -133,7 +133,7 @@ It's important to note that ts-loader will need to run before any other loader t The same goes for [awesome-typescript-loader](https://github.com/TypeStrong/ts-loader), another TypeScript loader for Webpack. You can read more about the differences between the two [here](https://github.com/s-panferov/awesome-typescript-loader#differences-between-ts-loader). -You can see an example of using Webpack in our [tutorial on React and Webpack](./React%20&%20Webpack.md). +You can see an example of using Webpack in our [tutorial on React and Webpack](/docs/handbook/react-&-webpack.html). ## Moving to TypeScript Files diff --git a/packages/documentation/copy/pt/tutorials/Babel with TypeScript.md b/packages/documentation/copy/pt/tutorials/Babel with TypeScript.md new file mode 100644 index 000000000000..1547a71449e7 --- /dev/null +++ b/packages/documentation/copy/pt/tutorials/Babel with TypeScript.md @@ -0,0 +1,49 @@ +--- +title: Usando Babel com TypeScript +layout: docs +permalink: /pt/docs/handbook/babel-with-typescript.html +oneline: Como criar um projeto híbrido com Babel + TypeScript +translatable: true +--- + +## Babel vs `tsc` para TypeScript + +Ao desenvolver um projeto JavaScript moderno, você pode se perguntar qual a forma correta de converter arquivos do TypeScript para o JavaScript. + +Várias vezes a resposta é _"depende"_, ou _"alguém pode ter decidido por você"_ dependendo do projeto. Se você está construindo seu projeto com algum framework existente como [tsdx](https://tsdx.io), [Angular](https://angular.io/), [NestJS](https://nestjs.com/) ou qualquer outro framework mencionado na seção [Começando com TypeScript](/docs/home) então essa decisão é sua. + +Contudo, uma heurística útil seria: + +- A saída do seu processo de build é, na maioria das vezes, igual aos arquivos de entrada? Use `tsc` +- Você precisa de um pipeline de build com múltiplas sáidas possíveis? Use `babel` para transpilar e `tsc` para checagem de tipo. + +## Babel para transpilar, `tsc` para tipos + +Esse é um padrão comum para projetos com infraestruturas de build já existentes e que têm sido portados de uma base de código JavaScript para TypeScript. + +Essa técnica é uma abordagem híbrida, usando o [preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript) do Babel para gerar seus arquivos JS, e então usar o TypeScript para fazer a checagem de tipos e gerar os arquivos `.d.ts`. + +Usando o suporte do babel para o Typescript, você consegue trabalhar com pipelines de build existentes e tem mais chances de gerar JS mais rápido porque o Babel não faz checagem de tipo no seu código. + +#### Checagem de Tipo e geração de arquivos .d.ts + +A desvantagem de usar babel é que você não tem checagem de tipos durante a transição do TS para o JS. Isso significa que erros de tipagem que você deixou passar no seu editor podem acabar no código de produção. + +Além disso, Babel não pode criar arquivos `.d.ts` para seu TypeScript o que pode fazer com que o trabalho fique mais difícil se seu projeto for uma biblioteca. + +Para corrigir esses problemas, você provavelmente vai querer configurar um comando para fazer a checagem de tipos do seu projeto usando TSC. Isso provavelmente significa duplicar algumas das suas configurações do babel para um [`tsconfig.json`](/tconfig) correspondente e garantir que estas diretivas estão ativadas: + +```json tsconfig +"compilerOptions": { + // Garante que arquivos .d.ts são criados pelo tsc, mas não arquivos .js + "declaration": true, + "emitDeclarationOnly": true, + // Garante que o Babel pode transpilar de maneira segura os arquivos no projeto TypeScript + "isolatedModules": true +} +``` + +Para mais informações sobre essas diretivas: + +- [`isolatedModules`](/tsconfig#isolatedModules) +- [`declaration`](/tsconfig#declaration), [`emitDeclarationOnly`](/tsconfig#emitDeclarationOnly) diff --git a/packages/documentation/scripts/generateDocsNavigationPerLanguage.js b/packages/documentation/scripts/generateDocsNavigationPerLanguage.js index ad5dafc2dc15..8532c9350a90 100644 --- a/packages/documentation/scripts/generateDocsNavigationPerLanguage.js +++ b/packages/documentation/scripts/generateDocsNavigationPerLanguage.js @@ -139,6 +139,7 @@ const handbookPages = [ summary: "Compiler configuration reference.", items: [ { file: "project-config/tsconfig.json.md" }, + { file: "project-config/Compiler Options in MSBuild.md" }, { href: "/tsconfig", title: "TSConfig Reference", @@ -146,7 +147,6 @@ const handbookPages = [ }, { file: "project-config/Compiler Options.md" }, { file: "project-config/Project References.md" }, - { file: "project-config/Compiler Options in MSBuild.md" }, { file: "project-config/Integrating with Build Tools.md" }, { file: "project-config/Configuring Watch.md" }, { file: "Nightly Builds.md" }, @@ -159,15 +159,15 @@ const handbookPages = [ beta: true, items: [ { file: "handbook-v2/Basics.md" }, - { file: "handbook-v2/Classes.md" }, { file: "handbook-v2/Everyday Types.md" }, - { file: "handbook-v2/Modules.md" }, - { file: "handbook-v2/More on Functions.md" }, - { file: "handbook-v2/Narrowing.md" }, { file: "handbook-v2/Object Types.md" }, { file: "handbook-v2/Type Declarations.md" }, + { file: "handbook-v2/Narrowing.md" }, + { file: "handbook-v2/More on Functions.md" }, { file: "handbook-v2/Types from Extraction.md" }, { file: "handbook-v2/Types from Transformation.md" }, + { file: "handbook-v2/Classes.md" }, + { file: "handbook-v2/Modules.md" }, { file: "handbook-v2/Understanding Errors.md" }, ], }, diff --git a/packages/gatsby-remark-shiki-twoslash/package.json b/packages/gatsby-remark-shiki-twoslash/package.json index f85f7d261eb5..4e18b261bd07 100644 --- a/packages/gatsby-remark-shiki-twoslash/package.json +++ b/packages/gatsby-remark-shiki-twoslash/package.json @@ -23,7 +23,7 @@ "@typescript/vfs": "1.3.0", "shiki": "^0.1.6", "shiki-languages": "^0.1.6", - "shiki-twoslash": "0.8.0", + "shiki-twoslash": "0.8.1", "typescript": "*", "unist-util-visit": "^2.0.0" }, diff --git a/packages/playground-examples/copy/en/JavaScript/Modern JavaScript/Immutability.ts b/packages/playground-examples/copy/en/JavaScript/Modern JavaScript/Immutability.ts index 49732a191252..477ccf9f71ca 100644 --- a/packages/playground-examples/copy/en/JavaScript/Modern JavaScript/Immutability.ts +++ b/packages/playground-examples/copy/en/JavaScript/Modern JavaScript/Immutability.ts @@ -54,4 +54,4 @@ myFrozenArray.push("World"); // section of the examples: // // example:literals -// example:type-type-widening-and-narrowing +// example:type-widening-and-narrowing diff --git a/packages/playground-examples/copy/id/3-7/Types and Code Flow/Assertion Functions.ts b/packages/playground-examples/copy/id/3-7/Types and Code Flow/Assertion Functions.ts new file mode 100644 index 000000000000..18c17813d2cd --- /dev/null +++ b/packages/playground-examples/copy/id/3-7/Types and Code Flow/Assertion Functions.ts @@ -0,0 +1,76 @@ +//// { compiler: { }, order: 1 } + +// Karena sifat JavaScript yang fleksibel, menambahkan pemeriksaan +// tipe data merupakan ide yang bagus untuk memastikan asumsi Anda + +// Hal-hal ini biasanya disebut _assertions_ (atau _invariants_) +// _Assertions_ merupakan sebuah fungsi kecil yang mengeluarkan pesan +// kesalahan dini ketika variabel yang diberikan tidak sesuai +// dengan apa yang Anda harapkan. + +// Node menyediakan fungsi bawaan untuk menyelesaikan masalah ini. +// Fungsi tersebut bernama `assert` dan fungsi tersebut tersedia +// tanpa harus melakukan `import` terlebih dahulu. + +// Sekarang, kita akan membuat fungsi `assert` kita sendiri. +// Kode program di bawah ini akan mendeklarasikan fungsi yang +// menegaskan bahwa ekspresi yang bernama `value` bernilai +// `true`. +declare function assert(value: unknown): asserts value; + +// Sekarang, kita akan menggunakan fungsi tersebut untuk +// memeriksa tipe dari sebuah `enum` +declare const mungkinAngkaAtauString: string | number; +assert(typeof mungkinAngkaAtauString === "string"); + +// Dengan TypeScript versi 3.7, fitur analisis alur kode dapat +// menggunakan fungsi-fungsi semacam ini untuk mengetahui +// maksud dari kode program. Jadi, ketika Anda menyorot +// variabel di bawah ini - Anda dapat melihat bahwa variabel +// tersebut telah dipersempit dari sebuah _string_ atau bilangan +// menjadi hanya sebuah _string_ + +mungkinAngkaAtauString; + +// Anda dapat menggunakan fungsi _assertion_ untuk menjamin +// tipe di seluruh kode program Anda, contohnya TypeScript +// mengetahui bahwa fungsi ini akan mengembalikan sebuah +// bilangan tanpa perlu penambahan tipe pada parameter +// melalui deklarasi _assert_ pada baris sebelumnya + +function perkalian(x: any, y: any) { + assert(typeof x === "number"); + assert(typeof y === "number"); + + return x * y; +} + +// Fungsi _assertion_ merupakan saudara dari _Type Guards_ +// Hal yang membedakan adalah _type-guards_ mempengaruhi alur +// kode seiring berjalannya fungsi. + +// Contohnya, kita dapat menggunakan fungsi _assertion_ untuk +// mempersempit tipe dari sebuah _enum_ seiring berjalannya +// waktu. + +declare const salahSatuDariLimaBilanganPertama: 1 | 2 | 3 | 4 | 5; + +declare function adalahGanjil(param: unknown): asserts param is 1 | 3 | 5; +declare function adalahDibawahEmpat(param: unknown): asserts param is 1 | 2 | 3 | 4; + +// Hal ini seharusnya mempersempit _enum_ menjadi: 1 | 3 | 5 + +adalahGanjil(salahSatuDariLimaBilanganPertama); +salahSatuDariLimaBilanganPertama; + +// Hal ini akan memotong nilai _enum_ yang mungkin menjadi: 1 | 3 + +adalahDibawahEmpat(salahSatuDariLimaBilanganPertama); +salahSatuDariLimaBilanganPertama; + +// Hal-hal diatas adalah dasar dari beberapa fitur yang dimiliki +// oleh fungsi _assertion_ pada TypeScript versi 3.7 - Anda dapat +// mengetahui lebih lanjut dengan membaca catatan rilis TypeScript +// versi 3.7: +// +// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/ diff --git a/packages/playground-examples/copy/id/3-7/Types and Code Flow/Recursive Type Reference.ts b/packages/playground-examples/copy/id/3-7/Types and Code Flow/Recursive Type Reference.ts new file mode 100644 index 000000000000..d85944baf880 --- /dev/null +++ b/packages/playground-examples/copy/id/3-7/Types and Code Flow/Recursive Type Reference.ts @@ -0,0 +1,43 @@ +//// { compiler: { }, order: 2 } + +// Memilih antara menggunakan tipe dan antarmuka adalah +// tentang memilih batasan dari fitur yang ditawarkan keduanya. +// Dengan TypeScript 3.7, salah satu batasan yang dimiliki +// oleh tipe namun tidak dimiliki antarmuka telah dihapus. + +// Anda dapat mengetahui lebih lanjut tentang hal ini pada +// example:types-vs-interfaces + +// Dulunya, Anda tidak dapat mengacu pada tipe yang Anda +// definiskan di dalam tipe itu sendiri. Hal ini adalah sebuah +// batasan yang tidak terdapat dalam sebuah antarmuka, dan dapat +// diatasi dengan sebuah cara tertentu. + +// Contohnya, ekspresi di bawah ini tidak valid pada TypeScript versi 3.6: +type NilaiAtauArray = T | Array>; + +// Di bawah ini merupakan cara untuk mengatasi masalah tersebut, dengan +// menggabungkan tipe dengan sebuah antarmuka +type NilaiAtauArray2 = T | ArrayOfNilaiAtauArray; +interface ArrayOfNilaiAtauArray extends Array> { } + +// Hal tersebut memungkinkan sebuah definisi JSON yang komprehensif, +// yang dinyatakan dengan mengacu pada dirinya sendiri. + +type Json = string | number | boolean | null | Json[] | { [key: string]: Json }; + +const contohStatusJSON: Json = { + tersedia: true, + namaPengguna: "Jean-loup", + ruangan: { + nama: "Highcrest", + // Tidak dapat menambahkan fungsi pada tipe Json + // perbarui: () => {} + }, +}; + +// Ada hal lain yang dapat dipelajari dari catatan rilis TypeScript versi +// 3.7 _beta_ dan _pull request_nya. +// +// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/ +// https://github.com/microsoft/TypeScript/pull/33050 diff --git a/packages/playground-examples/copy/id/3-7/Types and Code Flow/Uncalled Function Checks.ts b/packages/playground-examples/copy/id/3-7/Types and Code Flow/Uncalled Function Checks.ts new file mode 100644 index 000000000000..8d56eb4e910c --- /dev/null +++ b/packages/playground-examples/copy/id/3-7/Types and Code Flow/Uncalled Function Checks.ts @@ -0,0 +1,42 @@ +//// { compiler: { }, order: 1 } + +// Terdapat sebuah fitur pada TypeScript versi 3.7, +// yaitu pemeriksaan pada pernyataan `if` ketika +// anda secara tidak sengaja menggunakan sebuah fungsi +// dimana seharusnya anda menggunakan nilai kembalian +// dari sebuah fungsi. + +// Hal ini hanya berlaku bila fungsi yang dimaksud ada, +// yang menyebabkan pernyataan `if` akan selalu bernilai `true`. + +// Di bawah ini merupakan sebuah contoh antarmuka _plugin_, +// dimana ada _callback_ yang harus ada dan _callback_ pilihan. +interface PengaturanPlugin { + pluginShouldLoad?: () => void; + pluginIsActivated: () => void; +} + +declare const plugin: PengaturanPlugin; + +// Karena _method_ `pluginShouldLoad` bisa saja tidak ada, +// maka pemeriksaan pada pernyataan `if` sah dilakukan. + +if (plugin.pluginShouldLoad) { + // Lakukan sesuatu ketika `pluginShouldLoad` ada. +} + +// Pada TypeScript versi 3.6 ke bawah, hal ini bukan merupakan sebuah kesalahan. + +if (plugin.pluginIsActivated) { + // Ingin melakukan sesuatu ketika _plugin_ diaktifkan, + // namun tidak dengan memanggil _method_ melainkan kita gunakan + // sebagai properti. +} + +// _Method_ `pluginIsActivated` seharusnya selalu ada, namun TypeScript +// tetap memperbolehkan pemeriksaan pada pernyataan `if`, karena _method_ +// tersebut dijalankan di dalam blok `if`. + +if (plugin.pluginIsActivated) { + plugin.pluginIsActivated(); +} diff --git a/packages/playground-examples/copy/id/3-8/Breaking Changes/Checking Unions with Index Signatures.ts b/packages/playground-examples/copy/id/3-8/Breaking Changes/Checking Unions with Index Signatures.ts new file mode 100644 index 000000000000..2cb21e079eeb --- /dev/null +++ b/packages/playground-examples/copy/id/3-8/Breaking Changes/Checking Unions with Index Signatures.ts @@ -0,0 +1,35 @@ +//// { compiler: { ts: "3.8.3" } } + +// Pada TypeScript versi sebelumnya, fitur pemeriksaan kode tidak akan +// memastikan _field_ yang tidak dideklarasikan dalam sebuah _union_ +// sesuai dengan tipe apapun yang terindeks pada _union_. + +// Anda dapat mempelajari lebih lanjut tentang tipe yang +// terindeks melalui: example:indexed-types + +// Sebagai contoh, tipe IdentifierCache dibawah ini menyatakan bahwa +// setiap _key_ pada objek tersebut merupakan sebuah angka: + +type IdentifierCache = { [key: string]: number }; + +// Hal tersebut menyebabkan ekspresi dibawah ini menjadi tidak valid, +// karena 'file_a' memiliki nilai sebuah _string_. + +const cacheDenganString: IdentifierCache = { file_a: "12343" }; + +// Namun, ketika Anda menyatakan hal tersebut dalam sebuah _union_, +// maka pemeriksaan kode tidak akan dijalankan: + +let cachePengguna: IdentifierCache | { index: number }; +cachePengguna = { file_pertama: 5, file_kedua: "abc" }; + +// Masalah tersebut sudah diperbaiki, dan akan ada +// sebuah pesan kesalahan mengenai 'file_kedua' dari kompilator. + +// Perbaikan tersebut juga sudah mampu mengangani kasus dimana _key_ +// memiliki tipe yang berbeda, contohnya ([key: string] dan [key: number]) + +type IdentifierResponseCache = { [key: number]: number }; + +let cacheHasil: IdentifierCache | IdentifierResponseCache; +cacheHasil = { file_pertama: "abc" }; diff --git a/packages/playground-examples/copy/id/3-8/JSDoc Improvements/Accessibility Modifiers.js b/packages/playground-examples/copy/id/3-8/JSDoc Improvements/Accessibility Modifiers.js new file mode 100644 index 000000000000..3dd8f4545c53 --- /dev/null +++ b/packages/playground-examples/copy/id/3-8/JSDoc Improvements/Accessibility Modifiers.js @@ -0,0 +1,80 @@ +//// { compiler: { ts: "3.8.3" }, isJavaScript: true } +// @ts-check + +// Dukungan JSDoc terhadap TypeScript telah diperluas untuk +// mendukung pengubah izin akses pada atribut kelas. Ada: +// +// @public - yang merupakan nilai anggapan. +// @private - atribut yang memiliki izin akses ini +// hanya dapat diakses pada kelas yang sama +// dimana atribut ini ditetapkan. +// @protected - atribut yang memiliki izin akses ini +// dapat diakses pada kelas dimana +// atribut ini ditetapkan dan kelas-kelas turunannya. + +// Di bawah ini merupakan sebuah kelas dasar yang bernama Binatang, +// kelas ini memiliki sebuah atribut `private` dan `protected`. +// Kelas turunan dari Binatang dapat mengakses "this.cepat" +// tapi tidak bisa mengakses "this.tipe". + +// Diluar kelas-kelas tersebut, kedua atribut tidak terlihat +// dan akan mengembalikan kesalahan kompilasi ketika // @ts-check +// diaktifkan. + +class Binatang { + constructor(tipe) { + /** @private */ + this.tipe = tipe + /** @protected */ + this.cepat = tipe === 'citah' + } + + bersuara() { + // Biasanya binatang ini jarang menimbulkan suara + if (this.tipe === 'bengal') { + console.log('') + } else { + throw new Error('bersuara dipanggil pada kelas dasar') + } + } +} + +class Kucing extends Binatang { + constructor(type) { + super(type || 'kucing rumahan') + } + + bersuara() { + console.log('meow') + } + + lari() { + if (this.cepat) { + console.log('Berhasil menjauh') + } else { + console.log('Gagal menjauh') + } + } +} + +class Citah extends Kucing { + constructor() { + super('citah') + } +} + +class Bengal extends Kucing { + constructor() { + super('bengal') + } +} + +const kucingRumahan = new Kucing() +kucingRumahan.bersuara() + +// Atribut-atribut di bawah ini tidak tersedia +kucingRumahan.tipe +kucingRumahan.cepat + +// Anda dapat mempelajari lebih lanjut melalui +// https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#jsdoc-modifiers diff --git a/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Export Modules From.ts b/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Export Modules From.ts new file mode 100644 index 000000000000..3c1918347c86 --- /dev/null +++ b/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Export Modules From.ts @@ -0,0 +1,27 @@ +//// { compiler: { ts: "3.8.3" } } + +// Kemampuan TypeScript untuk mengekspor ulang menjadi lebih dekat +// pada kasus tambahan yang terdapat pada ES2018 +// +// Ekspor pada JavaScript mempunyai kemampuan untuk mengekspor +// ulang sebuah bagian dari _dependency_ secara elegan: + +export { ScriptTransformer } from "@jest/transform"; + +// Ketika Anda ingin mengekspor seluruh objek, hal +// tersebut menjadi agak sedikit berlebih pada TypeScript +// versi sebelumnya: + +import * as console from "@jest/console"; +import * as reporters from "@jest/reporters"; + +export { console, reporters }; + +// Pada TypeScript versi 3.8, TypeScript mendukung +// lebih banyak ekspresi ekspor dibandingkan spesifikasi +// JavaScript, dimana hal tersebut memperbolehkan Anda +// untuk menulis ekspresi ekspor ulang sebuah modul +// hanya dengan satu baris saja + +export * as jestConsole from "@jest/console"; +export * as jestReporters from "@jest/reporters"; diff --git a/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Private Class Fields.ts b/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Private Class Fields.ts new file mode 100644 index 000000000000..04bee0a3d73a --- /dev/null +++ b/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Private Class Fields.ts @@ -0,0 +1,81 @@ +//// { compiler: { ts: "3.8.3" } } + +// TypeScript versi 3.8, menambahkan atribut `private`, dimana hal tersebut +// merupakan sebuah cara untuk mendeklarasikan sebuah atribut kelas +// yang tidak dapat diakses diluar kelas tempat atribut tersebut +// dinyatakan, termasuk oleh kelas turunannya. + +// Sebagai contoh, kelas Orang di bawah ini tidak mengizinkan siapapun +// menggunakan objek dari kelas tersebut untuk membaca nama depan, +// nama belakang, atau prefiks + +class Orang { + #namaDepan: string; + #namaBelakang: string; + #prefiks: string; + + constructor(namaDepan: string, namaBelakang: string, prefiks: string) { + this.#namaDepan = namaDepan; + this.#namaBelakang = namaBelakang; + this.#prefiks = prefiks; + } + + sapa() { + // Di Islandia, nama lengkap lebih umum digunakan dibandingkan + // bentuk [prefix] [nama belakang] + // https://www.w3.org/International/questions/qa-personal-names#patronymic + if (navigator.languages[0] === "is") { + console.log(`Góðan dag, ${this.#namaDepan} ${this.#namaBelakang}`); + } else { + console.log(`Halo, ${this.#prefiks} ${this.#namaBelakang}`); + } + } +} + +let jeremy = new Orang("Jeremy", "Bearimy", "Mr"); + +// Anda tidak dapat mengakses atribut `private` di luar kelas tersebut: + +// Sebagai contoh, ekspresi di bawah ini tidak valid: +console.log(jeremy.#namaBelakang); + +// Begitu pun ekspresi di bawah ini: +console.log("Nama belakang orang adalah:", jeremy["#namaBelakang"]); + +// Pertanyaan umum yang seringkali kami dapatkan adalah +// "Mengapa Anda memilih cara ini dibandingkan kata kunci `private` pada +// sebuah atribut kelas?" - mari kita bandingkan kedua hal tersebut +// dengan membandingkan cara kerjanya pada TypeScript sebelum versi 3.8: + +class Anjing { + private _nama: string; + constructor(nama: string) { + this._nama = nama; + } +} + +let oby = new Anjing("Oby"); +// Pernyataan tersebut tidak memperbolehkan Anda mengakses atribut +// nama menggunakan notasi titik. +oby._nama = "Spot"; +// Namun, TypeScript memperbolehkan pengaksesan atribut sebagai +// jalan keluarnya. +oby["_nama"] = "Cherny"; + +// Referensi TypeScript pada sebuah atribut `private` hanya tersedia +// pada tingkat tipe saja yang berarti Anda hanya dapat mempercayai +// izin akses sampai tingkat tersebut saja. Melalui atribut `private` +// yang akan menjadi bagian dari bahasa JavaScript, maka Anda dapat +// membuat jaminan yang lebih baik mengenai visibilitas pada kode +// program Anda. + +// Kami tidak berencana untuk menghapus dukungan terhadap +// kata kunci `private` pada TypeScript, sehingga kode program +// Anda tetap dapat dijalankan, namun sekarang Anda dapat menulis +// kode program yang lebih dekat dengan bahasa JavaScript. + +// Anda dapat mempelajari lebih lanjut tentang atribut kelas +// pada proposal tc39 +// https://github.com/tc39/proposal-class-fields/ +// dan catatan rilis _beta_: +// https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields diff --git a/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Type Imports.tsx b/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Type Imports.tsx new file mode 100644 index 000000000000..889344b4f7b0 --- /dev/null +++ b/packages/playground-examples/copy/id/3-8/Syntax and Messaging/Type Imports.tsx @@ -0,0 +1,58 @@ +//// { compiler: { ts: "3.8.3" } } + +// Pada TypeScript versi 3.8, kami menambahkan sintaks baru +// untuk mengimpor tipe, yang akan terasa familiar bagi +// pengguna yang datang dari flow. + +// `import type` menjadi cara untuk mendeklarasikan sebuah +// impor yang hanya mengimpor tipe. Hal tersebut akan membuat +// Anda menjadi lebih yakin bahwa potongan kode tersebut akan +// dihapus ketika kode program diubah menjadi JavaScript dengan +// cara yang lebih mudah diprediksi karena kode tersebut pasti +// akan dihapus! + +// Sebagai contoh, baris kode di bawah ini tidak akan menambahkan +// sebuah pernyataan `import` atau `require` +import type { CSSProperties } from "react"; + +// Tipe tersebut akan digunakan pada baris kode di bawah ini: +const style: CSSProperties = { + textAlign: "center", +}; + +// Hal ini berbanding terbalik dengan pernyataan impor di bawah ini: +import * as React from "react"; + +// Yang akan dimasukkan pada kode JavaScript +export class SelamatDatang extends React.Component { + render() { + return ( +
+

Halo dunia

+
+ ); + } +} + +// Namun, bila pernyataan impor dilakukan tanpa kata kunci `type` +// dan hanya mengimpor sebuah tipe menggunakan pernyataan 'import' +// biasa - pernyataan tersebut bisa dihapus. Jika Anda melihat +// pada berkas JavaScript hasil kompilasi, impor di bawah ini +// tidak dimasukkan pada kode program. + +import { FunctionComponent } from "react"; + +export const PengumumanBeta: FunctionComponent = () => { + return

Halaman ini masih dalam tahap beta

; +}; + +// Hal ini disebut sebagai _import elision_, dan hal tersebut +// dapat menjadi sumber kebingungan. Sintaks `import type` +// memperbolehkan Anda untuk menuliskan apa yang Anda inginkan +// secara lebih spesifik pada JavaScript. + +// Dokumen ini merupakan gambaran singkat dari kasus penggunaan +// utama dari `import types` namun ada kasus penggunaan lainnya +// yang Anda dapat pelajari pada catatan rilis TypeScript versi 3.8 + +// https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#type-only-imports-exports diff --git a/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Code Flow.ts b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Code Flow.ts new file mode 100644 index 000000000000..5a433facd4fa --- /dev/null +++ b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Code Flow.ts @@ -0,0 +1,67 @@ +//// { order: 3, compiler: { strictNullChecks: true } } + +//// {order: 3, compiler: {strictNullChecks: true}} + +// Bagaimana kode mengalir di dalam file JavaScript dapat mempengaruhi +// tipe data di seluruh program kita. + +const users = [{ name: "Ahmed" }, { name: "Gemma" }, { name: "Jon" }]; + +// Kita akan melihat apakah kita dapat menemukan pengguna bernama "jon". +const jon = users.find(u => u.name === "jon"); + +// Dalam kasus di atas, 'find' bisa gagal. Dalam hal ini kita +// tidak memiliki objek. Ini menghasilkan sebuah tipe data: +// +// {name: string} | undefined +// +// Jika Anda mengarahkan mouse ke tiga penggunaan 'jon' berikut, +// Anda akan melihat bagaimana tipe berubah tergantung di mana kata tersebut berada: + +if (jon) { + jon; +} else { + jon; +} + +// Tipe '{name: string} | undefined' menggunakan fitur TypeScript +// yang disebut tipe data gabungan (_union types_). Tipe data gabungan +// adalah cara untuk nyatakan bahwa sebuah objek bisa +// menjadi salah satu dari banyak hal. +// +// Tanda pipa (|) bertindak sebagai pemisah antara tipe data yang berbeda. +// Sifat dinamis JavaScript berarti bahwa banyak fungsi +// menerima dan dan mengembalikan objek dari tipe data yang tidak terkait +// dan kita perlu untuk dapat mengungkapkan tipe data mana yang mungkin +// kita hadapi. + +// Kita bisa menggunakan ini dalam beberapa cara. Mari kita mulai dengan melihat +// himpunan (_array_) yang nilainya memiliki tipe berbeda. + +const identifiers = ["Hello", "World", 24, 19]; + +// Kita bisa menggunakan sintaks javascript 'type x === y' untuk +// memeriksa jenis elemen pertama. Anda dapat mengarahkan kursor ke atas +// 'randomIdentifier' di bawah untuk melihat perubahannya +// lokasi berbeda + +const randomIdentifier = identifiers[0]; +if (typeof randomIdentifier === "number") { + randomIdentifier; +} else { + randomIdentifier; +} + +// Analisis aliran kontrol ini berarti kita dapat menulis +// JavaScript polos, dan TypeScript akan mencoba memahami bagaimana file +// jenis kode akan berubah di lokasi berbeda. + +// Untuk mempelajari lebih lanjut tentang analisis aliran kode: +// - example:type-guards + +// Untuk melanjutkan membaca contoh-contoh lain, Anda dapat melompat ke +// beberapa tempat lain sekarang: +// +// - Modern JavaScript: example:immutability +// - Type Guards: example:type-guards +// - Functional Programming with JavaScript example:function-chaining diff --git a/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Functions.ts b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Functions.ts new file mode 100644 index 000000000000..274ed9c630a7 --- /dev/null +++ b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Functions.ts @@ -0,0 +1,92 @@ +//// { order: 2, compiler: { noImplicitAny: false } } + +// Ada beberapa cara untuk mendeklarasikan fungsi di +// JavaScript. Mari kita lihat fungsi yang menambahkan dua +// angka bersama: + +// Membuat fungsi dalam lingkup global yang disebut addOldSchool +function addOldSchool(x, y) { + return x + y; +} + +// Anda dapat memindahkan nama fungsi ke variabel +// nama juga +const anonymousOldSchoolFunction = function (x, y) { + return x + y; +}; + +// Anda juga dapat menggunakan singkatan panah-gemuk (_fat-arrow_) +// untuk suatu fungsi +const addFunction = (x, y) => { + return x + y; +}; + +// Kita akan fokus pada cara terakhir, tapi semuanya +// berlaku untuk ketiga format termasuk dua yang sebelumnya. + +// TypeScript menyediakan sintaks tambahan yang ditambahkan ke +// definisi fungsi dan menawarkan petunjuk tentang tipe data apa +// diharapkan oleh fungsi ini. +// +// Selanjutnya adalah versi paling terbuka dari fungsi add, versi ini +// mengatakan bahwa add mengambil dua masukan dari jenis +// apa pun: dimana masukan ini bisa berupa _string_, angka atau objek +// yang telah Anda buat. + +const add1 = (x: any, y: any) => { + return x + y; +}; +add1("Hello", 23); + +// Ini adalah JavaScript yang sah (_string_ dapat ditambahkan +// seperti ini misalnya) tetapi tidak optimal untuk fungsi kita +// yang kita tahu adalah angka, jadi kita akan mengonversi x dan +// y hanya menjadi angka. + +const add2 = (x: number, y: number) => { + return x + y; +}; +add2(16, 23); +add2("Hello", 23); + +// Bagus. Kita mendapatkan kesalahan ketika ada selain angka +// yang diteruskan ke dalam fungsi. Jika Anda mengarahkan kursor +// ke kata add2 di atas, Anda akan melihat bahwa TypeScript +// mendeskripsikannya sebagai: +// +// const add2: (x: number, y: number) => number +// +// Di mana ia menyimpulkan bahwa ketika dua input merupakan +// nomor, maka satu-satunya jenis pengembalian yang mungkin adalah nomor. +// Ini bagus, Anda tidak perlu menulis sintaks tambahan. +// Mari kita lihat apa yang diperlukan untuk melakukan itu: + +const add3 = (x: number, y: number): string => { + return x + y; +}; + +// Fungsi ini gagal karena kita memberi tahu TypeScript bahwa TypeScipt +// seharusnya menerima nilai kembali dalam bentuk _string_, tetapi +// ternyata fungsinya tidak memenuhi janji itu. + +const add4 = (x: number, y: number): number => { + return x + y; +}; + +// Ini adalah versi yang sangat eksplisit dari add2 - ada +// kasus ketika Anda ingin menggunakan sintaks tipe pengembalian eksplisit +// untuk memberi diri Anda ruang untuk bekerja sebelumnya +// Anda memulai. Agak mirip seperti bagaimana test-driven development +// merekomendasikan memulai dengan tes yang gagal, tetapi dalam kasus ini +// ini dengan bentuk fungsi yang gagal. + +// Contoh ini hanyalah dasar, Anda dapat mempelajari lebih banyak lagi +// tentang bagaimana fungsi bekerja di TypeScript di buku pegangan +// (handbook) dan di dalam bagian JavaScript Fungsional dari contoh: +// +// https://www.typescriptlang.org/docs/handbook/functions.html +// example:function-chaining + +// Dan untuk melanjutkan tur dasar-dasar JavaScript, +// kita akan melihat bagaimana aliran kode memengaruhi tipe data TypeScript: +// example:code-flow diff --git a/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Hello World.ts b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Hello World.ts new file mode 100644 index 000000000000..dac141e5d597 --- /dev/null +++ b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Hello World.ts @@ -0,0 +1,36 @@ +//// { order: 0, compiler: { target: 1 } } + +// Selamat datang di area bermain TypeScript. Situs ini mirip +// seperti menjalankan proyek TypeScript di dalam peramban web. + +// Area bermain memudahkan Anda bereksperimen dengan aman +// dengan ide-ide dalam bahasa TypeScript, dengan membuat +// proyek ini mudah untuk dibagikan. Semua yang diperlukan +// untuk memuat proyek untuk orang lain bisa dilakukan +// dengan memuat URL ini. + +const halo = "Halo"; + +// Anda dapat melihat di sebelah kanan hasil dari kompilator +// TypeScript: ini adalah kode JavaScript polos yang dapat +// dijalankan di peramban, server, atau di mana saja. + +const dunia = "Dunia"; + +// Anda dapat melihat bagaimana kompilator Typescript membuat +// perubahan kecil pada kode, dengan mengonversi "const" +// menjadi "var". Ini salah satu dari sekian banyak +// hal-hal yang dilakukan TypeScript agar dapat dijalankan +// di mana saja JavaScript bisa dijalankan. + +console.log(halo + " " + dunia); + +// Karena sekarang Anda sudah mengetahui cara kerja area bermain, +// mari kita lihat bagaimana TypeScript bisa membuat bekerja dengan +// JavaScript jadi lebih menyenangkan. Pada bagian ini kami akan mencoba +// menjaga agar kode yang ada menjadi sedekat mungkin dengan JavaScript polos +// agar Anda dapat menggunakan ulang pengetahuan JavaScript Anda. +// +// Klik di bawah untuk melanjutkan: +// +// example:objects-and-arrays diff --git a/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Objects and Arrays.ts b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Objects and Arrays.ts new file mode 100644 index 000000000000..de74996822fe --- /dev/null +++ b/packages/playground-examples/copy/id/JavaScript/JavaScript Essentials/Objects and Arrays.ts @@ -0,0 +1,113 @@ +//// { order: 1, compiler: { strict: false } } + +// Objek JavaScript merupakan kumpulan nilai-nilai yang +// dibungkus menggunakan kata kunci yang memiliki nama. + +const userAccount = { + name: "Kieron", + id: 0, +}; + +// Anda dapat menggabungkan objek-objek ini untuk +// membuat model data yang lebih besar dan lebih rumit. + +const pie = { + type: "Apple", +}; + +const purchaseOrder = { + owner: userAccount, + item: pie, +}; + +// Jika Anda menggunakan tetikus untuk mengarahkan +// kursor ke beberapa kata ini (coba arahkan kursor +// ke objek purchaseOrder di atas) Anda dapat melihat +// bagaimana TypeScript menafsirkan JavaScript Anda menjadi +// tipe data berlabel. + +// Nilai dapat diakses melalui ".", Jadi untuk mendapatkan +// nama pengguna untuk pesanan pembelian: +console.log(purchaseOrder.item.type); + +// Jika Anda mengarahkan kursor tetikus ke setiap bagian kode +// antara tanda (), Anda dapat melihat TypeScript menampilkan lebih banyak +// informasi tentang tiap-tiap bagian. Coba tulis ulang kode di bawah ini: + +// Salin ini di baris berikutnya, karakter demi karakter: +// +// purchaseOrder.item.type + +// TypeScript memberikan umpan balik ke area bermain +// tentang objek JavaScript apa saja yang tersedia di berkas ini +// dan memungkinkan Anda menghindari kesalahan ketik dan melihat tambahan +// informasi tanpa harus mencarinya di tempat lain. + +// TypeScript juga menawarkan fitur yang sama untuk himpunan (_array_). +// Berikut adalah himpunan yang isinya hanya pesanan pembelian +// yang kita buat. + +const allOrders = [purchaseOrder]; + +// Jika Anda mengarahkan kursor ke allOrders, Anda dapat +// mengetahui bahwa itu adalah himpunan karena info _hover_ +// diakhiri dengan []. Anda dapat mengakses +// urutan pertama menggunakan tanda kurung siku dengan indeks +// (mulai dari nol). + +const firstOrder = allOrders[0]; +console.log(firstOrder.item.type); + +// Cara alternatif untuk mendapatkan objek adalah dengan memencet (_popping_) +// himpunan untuk menghapus objek. Dengan melakukan ini, kita bisa +// menghapus objek dari himpunan, dan mengembalikan objek. Ini disebut +// mutasi himpunan, karena mengubah data di dalamnya. + +const poppedFirstOrder = allOrders.pop(); + +// Sekarang allOrders menjadi kosong. Mutasi data dapat bermanfaat untuk +// banyak hal, tapi satu cara untuk mengurangi kerumitan di +// basis kode Anda adalah dengan menghindari mutasi. TypeScript menawarkan cara +// untuk mendeklarasikan himpunan hanya baca (_read-only_): + +// Membuat tipe data berdasarkan bentuk pesanan pembelian: +type PurchaseOrder = typeof purchaseOrder; + +// Membuat himpunan pesanan pembelian yang hanya bisa dibaca +const readonlyOrders: readonly PurchaseOrder[] = [purchaseOrder]; + +// Ya! Agak lebih banyak kode memang. Ada empat +// hal-hal baru di sini: +// +// type PurchaseOrder - Menyatakan tipe data baru ke TypeScript. +// +// typeof - Gunakan sistem inferensi tipe data (_type inference_) untuk +// menyetel tipe data berdasarkan konstanta yang diteruskan berikutnya. +// +// purchaseOrder - Dapatkan variabel purchaseOrder dan beri tahu +// TypeScript ini adalah bentuk dari semua +// objek didalam himpunan pesanan. +// +// readonly - Objek ini tidak mendukung mutasi, sekali +// objek ini dibuat maka isi himpunan +// akan selalu sama. +// +// Sekarang jika Anda mencoba untuk keluar dari readonlyOrders, TypeScript +// akan memunculkan kesalahan. + +readonlyOrders.pop(); + +// Anda bisa menggunakan _readonly_ di semua tempat, +// sedikit lebih banyak sintaks tambahan di sana-sini, tapi sintaks +// ini memberikan lebih banyak keamanan ekstra. + +// Anda dapat mengetahui lebih lanjut tentang readonly: +// - https://www.typescriptlang.org/docs/handbook/interfaces.html#readonly-properties +// - https://basarat.gitbooks.io/typescript/content/docs/types/readonly.html + +// Dan Anda bisa terus belajar tentang JavaScript dan +// TypeScript didalam contoh tentang fungsi: +// example:functions +// +// Atau jika Anda ingin tahu lebih banyak tentang immutability: +// example:immutability diff --git a/packages/playground-examples/copy/ko/JavaScript/JavaScript Essentials/Hello World.ts b/packages/playground-examples/copy/ko/JavaScript/JavaScript Essentials/Hello World.ts new file mode 100644 index 000000000000..fcb0bb8dd12d --- /dev/null +++ b/packages/playground-examples/copy/ko/JavaScript/JavaScript Essentials/Hello World.ts @@ -0,0 +1,34 @@ +//// { order: 0, compiler: { target: 1 } } + +// TypeScript 플레이그라운드에 오신 것을 환영합니다. +// 이곳은 TypeScript를 웹 브라우저에서 실행하는 환경과 거의 비슷합니다. + +// 플레이그라운드에서 간단하게 +// 프로젝트를 공유할 수 있기 때문에, TypeScript로 아이디어를 +// 쉽고 안전하게 실험할 수 있습니다. 이 페이지의 URL만 +// 다른 사람에게 공유하면 됩니다. + +const hello = "Hello"; + +// 오른쪽에서 TypeScript 컴파일러의 결과를 볼 수 +// 있습니다. 결과는 브라우저나 서버 및 어디에서나 +// 실제로 실행할 수 있는 vanilla JavaScript입니다. + +const world = "World"; + +// "const"를 "var"로 변환하면 코드에서 작은 변화를 +// 확인할 수 있습니다. 이것은 TypeScript를 +// 모든 JavaScript 환경에서 실행 가능하도록 +// 수행하는 많은 작업 중 하나입니다. + +console.log(hello + " " + world); + +// 이제 플레이그라운드가 어떻게 동작하는지 알게 되었으니, +// TypeScript가 JavaScript 작업을 더 즐겁게 만드는 방법을 알아봅시다. +// 여기서는 어떻게 기존 지식을 재사용할 수 있는지 +// 보여주기 위해, 가능한 한 vanilla JavaScript에 +// 가깝게 유지하겠습니다. +// +// 계속하려면 아래를 클릭하세요: +// +// example:objects-and-arrays diff --git a/packages/playground-examples/copy/ko/TypeScript/Language Extensions/Enums.ts b/packages/playground-examples/copy/ko/TypeScript/Language Extensions/Enums.ts new file mode 100644 index 000000000000..3a944e153a0e --- /dev/null +++ b/packages/playground-examples/copy/ko/TypeScript/Language Extensions/Enums.ts @@ -0,0 +1,81 @@ +// 열거형은 TypeScript로 쓰는 JavaScript에 추가된 기능입니다. +// 이를 통해 이름 붙은 변수들의 집합을 쉽게 다룰 수 있습니다. + +// 기본적으로 열거형은 0부터 시작하는 숫자 기반이며, +// 각 항목은 1씩 증가하여 할당됩니다. +// 이는 값이 중요하지 않을 때 유용합니다. + +enum CompassDirection { + North, + East, + South, + West, +} + +// 열거 항목을 표기하여 값을 지정할 수 있으며, +// 그 값에서부터 증가가 시작됩니다: + +enum StatusCodes { + OK = 200, + BadRequest = 400, + Unauthorized, + PaymentRequired, + Forbidden, + NotFound, +} + +// EnumName.Value을 사용하여 열거형을 참조할 수 있습니다. + +const startingDirection = CompassDirection.East; +const currentStatus = StatusCodes.OK; + +// 열거형을 사용하여 key에서 value, 그리고 value에서 key 모든 방향으로 +// 데이터에 접근할 수 있습니다. + +const okNumber = StatusCodes.OK; +const okNumberIndex = StatusCodes["OK"]; +const stringBadRequest = StatusCodes[400]; + +// 열거형은 여러 타입일 수 있지만, 일반적으로 string 타입입니다. +// string을 사용하면 디버깅이 쉬워지는데, +// 런타임에서의 값을 통해 숫자를 찾아볼 필요가 없어지기 때문입니다. + +enum GamePadInput { + Up = "UP", + Down = "DOWN", + Left = "LEFT", + Right = "RIGHT", +} + +// 만약 JavaScript 런타임에서 사용되는 객체의 수를 줄이고 싶다면, +// const enum을 쓸 수 있습니다. + +// const enum의 값은 +// 런타임에서 객체를 통해 찾아지는 대신 +// 코드를 트랜스파일하는 과정에서 대체됩니다. + +const enum MouseAction { + MouseDown, + MouseUpOutside, + MouseUpInside, +} + +const handleMouseAction = (action: MouseAction) => { + switch (action) { + case MouseAction.MouseDown: + console.log("Mouse Down"); + break; + } +}; + +// 트랜스파일된 JavaScript 코드를 보면, +// 다른 열거형들이 객체나 함수 형태로 존재하는 것을 볼 수 있지만, +// MouseAction은 그렇지 않습니다. + +// 이는 handleMouseAction 안의 switch문에 있는 +// MouseAction.MouseDown의 경우에도 마찬가지입니다. + +// 열거형에는 이것보다 더 많은 기능이 있습니다. +// TypeScript 핸드북에서 더 알아볼 수 있습니다. +// +// https://www.typescriptlang.org/docs/handbook/enums.html diff --git a/packages/playground-examples/copy/ko/TypeScript/Language Extensions/Types vs Interfaces.ts b/packages/playground-examples/copy/ko/TypeScript/Language Extensions/Types vs Interfaces.ts new file mode 100644 index 000000000000..8e2107372946 --- /dev/null +++ b/packages/playground-examples/copy/ko/TypeScript/Language Extensions/Types vs Interfaces.ts @@ -0,0 +1,83 @@ +// 객체 형태를 선언하는 주요 도구는 두 가지가 있습니다. +// 인터페이스와 타입 별칭입니다. +// +// 이 둘은 무척 비슷하며, +// 대부분 동일하게 작동합니다. + +type BirdType = { + wings: 2; +}; + +interface BirdInterface { + wings: 2; +} + +const bird1: BirdType = { wings: 2 }; +const bird2: BirdInterface = { wings: 2 }; + +// TypeScript는 구조적 타입 시스템을 따르기 때문에, +// 교차하여 사용하는 것도 가능합니다. + +const bird3: BirdInterface = bird1; + +// 둘 다 다른 인터페이스와 타입으로의 확장이 가능합니다. +// 타입 별칭은 교차 타입을 통해 이를 수행하는 반면, +// 인터페이스는 키워드를 사용합니다. + +type Owl = { nocturnal: true } & BirdType; +type Robin = { nocturnal: false } & BirdInterface; + +interface Peacock extends BirdType { + colourful: true; + flies: false; +} +interface Chicken extends BirdInterface { + colourful: false; + flies: false; +} + +let owl: Owl = { wings: 2, nocturnal: true }; +let chicken: Chicken = { wings: 2, colourful: false, flies: false }; + +// 그래도 타입 별칭보다 인터페이스를 쓰는 것을 추천합니다. +// 분명히 더 나은 에러 메시지를 받을 수 있기 때문입니다. +// 뒤따르는 에러에 커서를 가져가면, +// Chicken과 같은 인터페이스를 사용했을 때 +// TypeScript가 더 간결하고 정확한 메시지를 어떻게 제공하는지 알 수 있습니다. + +owl = chicken; +chicken = owl; + +// 타입 별칭과 인터페이스 사이 한 가지 주요한 차이점은 +// 인터페이스는 열려 있고 타입 별칭은 닫혀 있다는 것입니다. +// 이는 인터페이스를 다음에 선언할 때 +// 확장할 수 있음을 의미합니다. + +interface Kitten { + purrs: boolean; +} + +interface Kitten { + colour: string; +} + +// 이와 달리 타입은 선언 바깥에서 +// 변경할 수 없습니다. + +type Puppy = { + color: string; +}; + +type Puppy = { + toys: number; +}; + +// 목적에 따라서, 이 차이는 좋을 수도 나쁠 수도 있습니다. +// 하지만 공개된 타입들의 경우, +// 그것들을 인터페이스로 만드는 것이 더 좋습니다. + +// 타입과 인터페이스에 대한 모든 엣지 케이스를 알고 싶다면, +// 아래 stack overflow thread가 +// 시작하기 좋은 훌륭한 자료가 될 것입니다. + +// https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types/52682220#52682220 diff --git a/packages/playground-examples/copy/ko/TypeScript/Primitives/Any.ts b/packages/playground-examples/copy/ko/TypeScript/Primitives/Any.ts new file mode 100644 index 000000000000..ee329a6287aa --- /dev/null +++ b/packages/playground-examples/copy/ko/TypeScript/Primitives/Any.ts @@ -0,0 +1,50 @@ +// any는 TypeScript의 탈출 구문입니다. +// 일부 코드를 JavaScript처럼 동적으로 동작하도록 선언하고 싶을 때, +// 또는 타입 시스템의 제한을 벗어나고 싶을 때 +// any를 사용할 수 있습니다. + +// JSON 파싱은 any의 좋은 예시입니다. + +const myObject = JSON.parse("{}"); + +// any를 사용한다는 것은 여러분이 코드를 더 잘 알고 있음을 뜻하기 때문에, +// 타입이 완전히 정확하지 않더라도 TypeScript는 코드가 안전하다고 인식합니다. +// 예를 들어, 아래 코드는 오류가 발생합니다. + +myObject.x.y.z; + +// any를 사용하면 타입의 안전성을 희생하는 대신 +// 코드를 원래의 JavaScript에 더욱 가깝게 작성할 수 있습니다. + +// any는 어떤 타입(never를 제외하고)이든 +// 다른 타입에 할당할 수 있도록 만드는 +// '타입 와일드카드'와도 같습니다. + +declare function debug(value: any): void; + +debug("a string"); +debug(23); +debug({ color: "blue" }); + +// 인수의 타입을 모두 any로 대신할 수 있기 때문에 +// debug의 각 호출이 허용됩니다. + +// TypeScript는 any의 위치를 +// 다양한 형태에서 고려합니다. +// 함수 인수로 사용되는 아래의 튜플이 그 예시입니다. + +declare function swap(x: [number, string]): [string, number]; + +declare const pair: [any, any]; +swap(pair); + +// pair의 첫 번째 any를 number로 대체하고, +// 두 번째 `any`를 string으로 대체하면서 인자가 매칭되기 때문에 +// swap 호출이 가능합니다. + +// 튜플을 처음 봤다면, 다음을 참고하세요: example:tuples + +// unknown은 any의 자매 타입입니다. +// 만약 any가 "뭐가 최선인지 알겠어"와 같다면, +// unknown은 "뭐가 최선일지 모르니까, TS에 타입을 알려줘"와 같습니다. +// example:unknown-and-never diff --git a/packages/playground-examples/copy/ko/TypeScript/Primitives/Literals.ts b/packages/playground-examples/copy/ko/TypeScript/Primitives/Literals.ts new file mode 100644 index 000000000000..112dae015178 --- /dev/null +++ b/packages/playground-examples/copy/ko/TypeScript/Primitives/Literals.ts @@ -0,0 +1,65 @@ +// TypeScript는 소스 코드에서 리터럴을 위한 +// 재미있고 특별한 기능들이 있습니다. + +// 여기선, 타입 넓히기와 좁히기 ( example:type-widening-narrowing )가 +// 중점적으로 다뤄지고 있으므로 +// 그 부분을 먼저 살펴보도록 하곘습니다. + +// 리터럴은 collection 타입의 더욱 구체적인 하위 타입입니다. +// 이는 "Hello World"는 string이지만, +// 타입 시스템에서 string은 "Hello World"가 아니라는 것을 의미합니다. + +const helloWorld = "Hello World"; +let hiWorld = "Hi World"; // 이것은 let이기 때문에 string입니다. + +// 이 함수는 모든 string을 받습니다. +declare function allowsAnyString(arg: string); +allowsAnyString(helloWorld); +allowsAnyString(hiWorld); + +// 이 함수는 "Hello World" string 리터럴만을 받습니다. +declare function allowsOnlyHello(arg: "Hello World"); +allowsOnlyHello(helloWorld); +allowsOnlyHello(hiWorld); + +// 이를 통해 특정 리터럴만을 받기 위해 union을 사용하는 +// API를 선언할 수 있습니다. + +declare function allowsFirstFiveNumbers(arg: 1 | 2 | 3 | 4 | 5); +allowsFirstFiveNumbers(1); +allowsFirstFiveNumbers(10); + +let potentiallyAnyNumber = 3; +allowsFirstFiveNumbers(potentiallyAnyNumber); + +// 언뜻 보기에, 이 규칙은 복잡한 객체들에는 적용되지 않습니다. + +const myUser = { + name: "Sabrina", +}; + +// 상수로 선언되어 있음에도 불구하고 이것이 어떻게 +// `name: "Sabrina"`를 `name: string`으로 바꾸는지 보세요. +// 이는 여전히 이름이 언제든 바뀔 수 있기 때문입니다. + +myUser.name = "Cynthia"; + +// myUser의 name 프로퍼티가 바뀔 수 있기 때문에, +// TypeScript는 타입 시스템에서 리터럴 버전을 사용할 수 없습니다. +// 하지만 이것을 가능하게끔 해주는 기능이 있습니다. + +const myUnchangingUser = { + name: "Fatma", +} as const; + +// mutable object는 바뀔 수 있는 대신, +// 객체에 "as const"가 적용되면, +// object 리터럴이 되어 바뀌지 않습니다. + +myUnchangingUser.name = "Raîssa"; + +// "as const"는 고정된 데이터를 다루는 좋은 도구이며, +// 코드를 한 줄의 리터럴로 적게끔 해줍니다. +// 또한 "as const"는 배열에서도 동작합니다. + +const exampleUsers = [{ name: "Brian" }, { name: "Fahrooq" }] as const; diff --git a/packages/playground-examples/copy/ko/sections.json b/packages/playground-examples/copy/ko/sections.json index 92782dc30c95..0c72f3f7bef0 100644 --- a/packages/playground-examples/copy/ko/sections.json +++ b/packages/playground-examples/copy/ko/sections.json @@ -1,33 +1,34 @@ { - "sections": [{ + "sections": [ + { "name": "JavaScript", "id": "JavaScript", - "subtitle": "See how TypeScript improves day to day working with JavaScript with minimal additional syntax." + "subtitle": "TypeScript가 최소한의 추가 구문으로 JavaScript 작업을 어떻게 개선하는지 확인해보세요." }, { "name": "TypeScript", "id": "TypeScript", - "subtitle": "Explore how TypeScript extends JavaScript to add more safety and tooling." + "subtitle": "TypeScript가 JavaScript를 확장하여 안전성과 도구를 추가하는 방법을 살펴보세요." }, { "name": "3.7", "id": "3.7", - "subtitle": "See the Release notes." + "subtitle": "릴리즈 노트를 확인해보세요." }, { "name": "3.8", "id": "3.8", - "subtitle": "See the Release notes." + "subtitle": "릴리즈 노트를 확인해보세요." }, { "name": "4.0", "id": "4.0", - "subtitle": "See the Release notes." + "subtitle": "릴리즈 노트를 확인해보세요." }, { "name": "Playground V3", "id": "Playground", - "subtitle": "Learn what has changed in this website." + "subtitle": "이 웹사이트에서 변경된 사항을 확인해보세요." } ], "sortedSubSections": [ @@ -59,4 +60,4 @@ "New TS Features", "New Checks" ] -} \ No newline at end of file +} diff --git a/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Immutability.ts b/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Immutability.ts index a4306a3601c6..8171db55b4ea 100644 --- a/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Immutability.ts +++ b/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Immutability.ts @@ -54,4 +54,4 @@ meuArrayCongelado.push("Mundo"); // na seção de exemplos do TypeScript: // // example:literals -// example:type-type-widening-and-narrowing +// example:type-widening-and-narrowing diff --git a/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Import Export.ts b/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Import Export.ts new file mode 100644 index 000000000000..4013637a2f8d --- /dev/null +++ b/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/Import Export.ts @@ -0,0 +1,108 @@ +//// { order: 1, target: "ES5" } + +// O JavaScript adicionou import/export à linguagem em 2016 +// e TypeScript tem suporte completo para esse estilo de +// conexão entre arquivos e entre modulos externos. +// O TypeScript expande essa sintaxe ao permitir que tipos +// sejam importados e exportados junto com o código. + +// Vamos ver o import de código de um módulo. + +import { danger, message, warn, DangerDSLType } from "danger"; + +// Aqui importamos um conjunto de import nomeados +// ("named imports") de um módulo do Node chamado danger. +// Apesar de haver mais do que quatro imports, +// esses são os únicos que nós escolhemos importar. + +// Nomeando especificamente quais imports você precisa, +// permite que ferramentas tenham a habilidade de remover +// código não utilizado em seu applicativo, e ajuda você a +// entender o que está sendo utilizado nessa arquivo em particular. + +// Nesse caso: danger, message e warn são imports de JavaScript +// enquanto que DangerDSLType é uma interface. + +// O TypeScript permite que engenheiros documentem seus códigos usando +// JSDoc, e a documentação é importada também. Por exemplo, se você +// passar o mouse sobre diferentes partes abaixo, você verá +// explicações sobre o que elas são. + +danger.git.modified_files; + +// Se você quiser saber como criar essas anotações de documentação +// leia o exemplo:jsdoc-support + +// Outro modo de importar código é através do export +// padrão de um módulo. Um exemplo disso é o módulo debug, o qual +// expõe uma função que cria uma função de log. + +import debug from "debug"; +const log = debug("playground"); +log("Código começou a rodar"); + +// Por conta das exports padrões ("default exports") não terem um nome, +// elas podem ser delicadas de se trabalhar junto com ferramentas de análise estática +// como o suporte a refactoração em TypeScript, mas elas têm o seu próprio uso. + +// Por haver uma longa história sobre import/export de código +// em JavaScript, existe uma parte confusa sobre o export padrão: +// alguns módulos exportados tem documentação que sugere que você possa +// escrever um import como este: + +import req from "request"; + +// Entretanto, isto apresenta uma erro. E então você encontra no +// Stack Overflow uma recomendação de import como esta: + +import * as req from "request"; + +// E este funciona. Por que? Nós vamos voltar a isso no final +// da nossa sessão sobre export. + +// Para realizar um import, você precisa fazer um export. +// O modo moderno de escrever exports é através da palavra-chave export + +/** O número atual de adesivos que sobraram no rolo */ +export const numeroDeAdesivos = 11; + +// Isso poderia ter sido importado em outro arquivo usando: +// +// import { numeroDeAdesivos } from "./caminho/para/o/arquivo" + +// Vocé pode ter tantas importações em um arquivo quantas forem necessárias. +// Já um export padrão é bem parecido com isso. + +/** Cria um adesivo para você */ +const geradorDeAdesivos = () => {}; +export default geradorDeAdesivos; + +// Isto poderia ser importado em outro arquivo usando: +// +// import pegueAdesivos from "./caminho/para/o/arquivo" +// +// O nome é decidido pelo módulo que está realizando o import. + +// Estes não são os únicos tipos de import, apenas os +// mais comuns em código moderno. Há um tópico bem abrangente +// sobre todos os modos que um código pode cruzar as fronteiras +// de um módulo no manual: +// +// https://www.typescriptlang.org/docs/handbook/modules.html + +// Entretanto, para tentar responder a última questão. Se você +// observar o código JavaScript desse exemplo, você verá isto: + +// var geradorDeAdesivos = function () { }; +// exports.default = geradorDeAdesivos; + +// Isso define a propriedade padrão ("default") no objeto exports como +// geradorDeAdesivos. Existe código que define o exports como uma +// função ao invés de um objeto. +// +// O TypeScript optou por utilizar a especificação ECMAScript +// sobre como lidar com esses casos, que é criar um erro. +// Entretanto, existe uma configuração do compilador que lida +// automaticamente com esses casos para você, que é a esModuleInterop. +// +// Se você ativar ela nesse exemplo, você verá que o erro desaparece. diff --git a/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/JSDoc Support.js b/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/JSDoc Support.js new file mode 100644 index 000000000000..5105538e1943 --- /dev/null +++ b/packages/playground-examples/copy/pt/JavaScript/Modern JavaScript/JSDoc Support.js @@ -0,0 +1,94 @@ +//// { order: 3, isJavaScript: true } + +// O TypeScript tem um suporte muito rico ao JSDoc, para muitos casos +// você pode até não utilizar arquivos .ts e apenas usar anotações de JSDoc +// para criar um ambiente de desenvolvimento rico. +// +// Um comentário JSDoc é um comentário de múltiplas linhas que +// começam com dois asteriscos ao invés de um. + +/* Este é um comentário normal */ +/** Este é um comentário JSDoc */ + +// Comentários JSDoc pertencem ao código JavaScript mais +// próximo abaixo dele + +const minhaVariavel = "Oi"; + +// Se você passar o mouse sobre minhaVariavel, você pode ver que +// ela tem o texto do comentário JSDoc acima. + +// Comentários JSDoc são um meio de fornecer para o TypeScript e editores +// informação sobre os tipos utilizados. Vamos começar com um fácil, +// definindo o tipo de uma variável como um tipo nativo. + +// Para todos os exemplos, você pode passar o mouse sobre o nome. +// E na próxima linha tente escrever [exemplo] para ver +// as opções de auto-complete. + +/** @type {number} */ +var meuNumero; + +// Você pode ver todas as tags disponíveis no manual: +// +// https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#supported-jsdoc + +// Entretanto, nós vamos tentar cobrir alguns exemplos a mais aqui. +// Você também pode copiar e colar aqui quaisquer exemplos do manual. + +// Importando tipos para arquivos de configuração em JavaScript. + +/** @type { import("webpack").Config } */ +const config = {}; + +// Criando um tipo complexo para reutilizar em múltiplos lugares: + +/** + * @typedef {Object} Usuario - a conta de um usuario + * @property {string} nome - o nome de usuario + * @property {number} id - um id único + */ + +// Então use-o através do nome do typedef: + +/** @type { Usuario } */ +const usuario = {}; + +// Existe em TypeScript uma definição de tipo em linha ("inline type shorthand") que é equivalente +// e a qual você pode usar para ambos: o type e o typedef. + +/** @type {{ dono: Usuario, nome: string }} */ +const recurso; + +/** @typedef {{dono: Usuario, nome: string}} Recurso */ + +/** @type {Recurso} */ +const outroRecurso; + + +// Declarando uma função com tipos: + +/** + * Adiciona dois números + * @param {number} a O primeiro número + * @param {number} b O segundo número + * @returns {number} + */ +function adicionaDoisNumeros(a, b) { + return a + b; +} + +// Você pode usar a maioria das ferramentas de tipos do TypeScript, como uniões ("unions"): + +/** @type {(string | boolean)} */ +let stringOuBoolean = ""; +stringOuBoolean = false; + +// Estender globais em JSDoc é um processo mais complicado +// que você pode conferir no manual do VS Code: +// +// https://code.visualstudio.com/docs/nodejs/working-with-javascript#_global-variables-and-type-checking + +// Adicionar comentários do JSDoc em suas funções é uma situação +// em que todos ganham. Você tem melhores ferramentas assim como +// todo os consumidores da sua API. diff --git a/packages/playground-examples/copy/pt/JavaScript/Working With Classes/Generic Classes.ts b/packages/playground-examples/copy/pt/JavaScript/Working With Classes/Generic Classes.ts new file mode 100644 index 000000000000..965ba568fa92 --- /dev/null +++ b/packages/playground-examples/copy/pt/JavaScript/Working With Classes/Generic Classes.ts @@ -0,0 +1,95 @@ +//// { order: 3 } + +// Este exemplo é, em sua maioria, em TypeScript, porque é um modo muito +// mais fácil de entender primeiro. Ao fim, nós iremos +// ver como criar a mesma classe, porém utilizando JSDoc. + +// Classes Genéricas são um meio de dizer que um tipo em particular +// depende de outro tipo. Por exemplo, aqui está uma gaveta +// que pode conter qualquer tipo de objeto, mas somente um tipo: + +class Gaveta { + conteudo: TipoDeRoupa[] = []; + + adicionar(objeto: TipoDeRoupa) { + this.conteudo.push(objeto); + } + + remover() { + return this.conteudo.pop(); + } +} + +// Para usar uma Gaveta você precisará trabalhar com outro tipo: + +interface Meia { + cor: string; +} + +interface Camiseta { + tamanho: "s" | "m" | "l"; +} + +// Nós podemos criar uma Gaveta somente para meias passando +// o tipo Meia quando criamos uma nova Gaveta: +const gavetaDeMeias = new Gaveta(); + +// Agora nós podemos adicionar ou remover meias na/da gaveta +gavetaDeMeias.adicionar({ cor: "branco" }); +const minhaMeia = gavetaDeMeias.remover(); + +// Assim como criar uma gaveta de Camisetas: +const gavetaDeCamisetas = new Gaveta(); +gavetaDeCamisetas.adicionar({ tamanho: "m" }); + +// Se você for um pouco excêntrico, você pode até criar +// uma gaveta que tem Meias e Camisetas usando para isso +// uma união ("union"): + +const gavetaMista = new Gaveta(); + +// Criar uma classe como a Gaveta sem a sintaxe do TypeScript +// requer o uso da tag "template" em JSDoc. +// Neste exemplo nós definimos a variável template, então +// definimos as propriedades da classe: + +// Para ter esse exemplo funcionando no playground, você terá +// que mudar as configurações para que seja um arquivo JavaScript, +// e apagar o código TypeScript acima. + +/** + * @template {{}} TipoDeRoupa + */ +class Comoda { + constructor() { + /** @type {TipoDeRoupa[]} */ + this.conteudo = []; + } + + /** @param {TipoDeRoupa} object */ + adicionar(objeto) { + this.conteudo.push(objeto); + } + + /** @return {TipoDeRoupa} */ + remover() { + return this.conteudo.pop(); + } +} + +// Então nós criamos um tipo novo através do JSDoc: + +/** + * @typedef {Object} Casaco uma roupa + * @property {string} cor cor do casaco + */ + +// Então, quando nós criamos uma nova instância daquela classe +// nós utilizamos @type para marcar a variável como uma Comoda +// que lida com Casacos + +/** @type {Comoda} */ +const comodaDeCasacos = new Comoda(); + +comodaDeCasacos.adicionar({ cor: "verde" }); +const casaco = comodaDeCasacos.remover(); diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index 3acc4ae661f1..e046c6cf8af6 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -160,7 +160,10 @@ export const createTypeScriptSandbox = ( // In the future it'd be good to add support for an 'add many files' const addLibraryToRuntime = (code: string, path: string) => { defaults.addExtraLib(code, path) - monaco.editor.createModel(code, "javascript", monaco.Uri.file(path)) + const uri = monaco.Uri.file(path) + if (monaco.editor.getModel(uri) === null) { + monaco.editor.createModel(code, "javascript", uri) + } config.logger.log(`[ATA] Adding ${path} to runtime`) } diff --git a/packages/shiki-twoslash/package.json b/packages/shiki-twoslash/package.json index 68a9e2826104..de360663a2d0 100644 --- a/packages/shiki-twoslash/package.json +++ b/packages/shiki-twoslash/package.json @@ -1,6 +1,6 @@ { "name": "shiki-twoslash", - "version": "0.8.0", + "version": "0.8.1", "license": "MIT", "homepage": "https://github.com/microsoft/TypeScript-Website/", "description": "API primitives to mix Shiki with Twoslash", diff --git a/packages/shiki-twoslash/src/dom.ts b/packages/shiki-twoslash/src/dom.ts index 102ea17b7891..a992299c29c5 100644 --- a/packages/shiki-twoslash/src/dom.ts +++ b/packages/shiki-twoslash/src/dom.ts @@ -36,6 +36,34 @@ const getRootRect = (element: HTMLElement): DOMRect => { return getRootRect(element.parentElement!) } +// Gets triggered on the spans inside the codeblocks +const hover = (event: Event) => { + const hovered = event.target as HTMLElement + if (hovered.nodeName !== "DATA-LSP") return resetHover() + + const message = hovered.getAttribute("lsp")! + const position = getAbsoluteElementPos(hovered) + + // Create or re-use the current hover div + const tooltip = findOrCreateTooltip() + + // Use a textarea to un-htmlencode for presenting to the user + var txt = document.createElement("textarea") + txt.innerHTML = message + tooltip.textContent = txt.value + + // Offset it a bit from the mouse and present it at an absolute position + const yOffset = 20 + tooltip.style.display = "block" + tooltip.style.top = `${position.top + yOffset}px` + tooltip.style.left = `${position.left}px` + + // limit the width of the tooltip to the outer container (pre) + const rootRect = getRootRect(hovered) + const relativeLeft = position.left - rootRect.x + tooltip.style.maxWidth = `${rootRect.width - relativeLeft}px` +} + /** * Creates the main mouse over popup for LSP info using the DOM API. * It is expected to be run inside a `useEffect` block inside your main @@ -47,7 +75,7 @@ const getRootRect = (element: HTMLElement): DOMRect => { * * export default () => { * // Add a the hovers - * useEffect(setupTwoslashHovers, []) + * useEffect(setupTwoslashHovers) * * // Normal JSX * return @@ -55,39 +83,15 @@ const getRootRect = (element: HTMLElement): DOMRect => { * */ export const setupTwoslashHovers = () => { - // prettier-ignore - const twoslashes = document.querySelectorAll(".shiki.lsp .code-container code") - - // Gets triggered on the spans inside the codeblocks - const hover = (event: Event) => { - const hovered = event.target as HTMLElement - if (hovered.nodeName !== "DATA-LSP") return resetHover() - - const message = hovered.getAttribute("lsp")! - const position = getAbsoluteElementPos(hovered) - - // Create or re-use the current hover div - const tooltip = findOrCreateTooltip() - - // Use a textarea to un-htmlencode for presenting to the user - var txt = document.createElement("textarea") - txt.innerHTML = message - tooltip.textContent = txt.value - - // Offset it a bit from the mouse and present it at an absolute position - const yOffset = 20 - tooltip.style.display = "block" - tooltip.style.top = `${position.top + yOffset}px` - tooltip.style.left = `${position.left}px` - - // limit the width of the tooltip to the outer container (pre) - const rootRect = getRootRect(hovered) - const relativeLeft = position.left - rootRect.x - tooltip.style.maxWidth = `${rootRect.width - relativeLeft}px` - } - - twoslashes.forEach(codeblock => { - codeblock.addEventListener("mouseover", hover) - codeblock.addEventListener("mouseout", resetHover) + const blocks = document.querySelectorAll(".shiki.lsp .code-container code") + blocks.forEach((code) => { + code.addEventListener("mouseover", hover) + code.addEventListener("mouseout", resetHover) }) + return () => { + blocks.forEach((code) => { + code.removeEventListener("mouseover", hover) + code.removeEventListener("mouseout", resetHover) + }) + } } diff --git a/packages/tsconfig-reference/copy/id/options/declaration.md b/packages/tsconfig-reference/copy/id/options/declaration.md new file mode 100644 index 000000000000..816b3adc738a --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/declaration.md @@ -0,0 +1,32 @@ +--- +display: "Declaration" +oneline: "Emit berkas d.ts untuk berkas referensi dalam proyek" +--- + +Buat berkas `.d.ts` untuk setiap berkas TypeScript atau JavaScript di dalam proyek Anda. +Berkas `.d.ts` ini adalah berkas definisi tipe yang menjelaskan API eksternal modul Anda. +Dengan berkas `.d.ts`, alat seperti TypeScript dapat menyediakan tipe yang masuk akal di dalam sumber kode tanpa definisi tipe data. + +Jika `declaration` disetel ke`true`, jalankan compiler dengan kode TypeScript: + +```ts twoslash +export let helloWorld = "hi"; +``` + +Akan menghasilkan berkas `index.js` seperti ini: + +```ts twoslash +// @showEmit +export let helloWorld = "hi"; +``` + +Dengan `helloWorld.d.ts` yang sesuai: + +```ts twoslash +// @showEmittedFile: index.d.ts +// @showEmit +// @declaration +export let helloWorld = "hi"; +``` + +Saat bekerja dengan berkas `.d.ts` untuk file JavaScript, Anda mungkin ingin menggunakan [`emitDeclarationOnly`](#emitDeclarationOnly) atau menggunakan [`outDir`](#outDir) untuk memastikan bahwa berkas JavaScript tidak ditimpa. \ No newline at end of file diff --git a/packages/tsconfig-reference/copy/id/options/declarationDir.md b/packages/tsconfig-reference/copy/id/options/declarationDir.md new file mode 100644 index 000000000000..e3f3341f3647 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/declarationDir.md @@ -0,0 +1,36 @@ +--- +display: "Declaration Dir" +oneline: "Atur direktori _root_ untuk berkas d.ts yang akan dituju" +--- + +Menawarkan cara untuk mengonfigurasi direktori _root_ tempat berkas deklarasi dihasilkan. + +``` +example +├── index.ts +├── package.json +└── tsconfig.json +``` + +dengan `tsconfig.json`; + +```json tsconfig +{ + "compilerOptions": { + "declaration": true, + "declarationDir": "./types" + } +} +``` + +Akan menempatkan d.ts untuk `index.ts` di direktori `types`: + +``` +example +├── index.js +├── index.ts +├── package.json +├── tsconfig.json +└── types + └── index.d.ts +``` \ No newline at end of file diff --git a/packages/tsconfig-reference/copy/id/options/declarationMap.md b/packages/tsconfig-reference/copy/id/options/declarationMap.md new file mode 100644 index 000000000000..0c7c24ab7d4a --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/declarationMap.md @@ -0,0 +1,9 @@ +--- +display: "_Declaration Map_" +oneline: "Buat peta sumber untuk berkas d.ts" +--- + +Menghasilkan peta sumber untuk berkas `.d.ts` yang mengarahkan kembali ke berkas sumber `.ts` asli. +Ini akan memungkinkan editor seperti VS Code untuk pergi ke file `.ts` asli saat menggunakan fitur seperti _Go to Definition_. + +Anda harus mempertimbangkan untuk mengaktifkan ini jika Anda menggunakan referensi proyek. diff --git a/packages/tsconfig-reference/copy/id/options/diagnostics.md b/packages/tsconfig-reference/copy/id/options/diagnostics.md new file mode 100644 index 000000000000..2a0ccb270490 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/diagnostics.md @@ -0,0 +1,8 @@ +--- +display: "Diagnostics" +oneline: "Mengeluarkan informasi tambahan setelah kompilasi" +--- + +Digunakan untuk mengeluarkan informasi diagnostik untuk _debugging_. Perintah ini adalah _subset_ dari [`extendedDiagnostics`](#extendedDiagnostics) yang lebih merupakan hasil yang dilihat pengguna, dan lebih mudah ditafsirkan. + +Jika Anda telah diminta oleh kompilator engineer TypeScript untuk memberikan hasil menggunakan tanda ini dalam sebuah kompilasi, di mana tidak ada salahnya menggunakan [`--extendedDiagnostics`](#extendedDiagnostics) sebagai gantinya. \ No newline at end of file diff --git a/packages/tsconfig-reference/copy/id/options/disableReferencedProjectLoad.md b/packages/tsconfig-reference/copy/id/options/disableReferencedProjectLoad.md new file mode 100644 index 000000000000..e177148fe6c4 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/disableReferencedProjectLoad.md @@ -0,0 +1,8 @@ +--- +display: "disableReferencedProjectLoad" +oneline: "Mengurangi jumlah proyek yang dimuat secara otomatis oleh TypeScript" +--- + +Dalam program TypeScript multi-proyek, TypeScript akan memuat semua proyek yang tersedia ke dalam memori untuk memberikan hasil yang akurat untuk tanggapan editor yang memerlukan grafik pengetahuan lengkap seperti 'Temukan Semua Referensi'. + +Jika proyek Anda besar, Anda dapat menggunakan saran `disableReferencedProjectLoad` untuk menonaktifkan pemuatan otomatis semua proyek. Sebaliknya, proyek dimuat secara dinamis saat Anda membuka file melalui editor Anda. \ No newline at end of file diff --git a/packages/tsconfig-reference/copy/id/options/disableSizeLimit.md b/packages/tsconfig-reference/copy/id/options/disableSizeLimit.md new file mode 100644 index 000000000000..0ae410cbc2a6 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/disableSizeLimit.md @@ -0,0 +1,6 @@ +--- +display: "Nonaktifkan Batas Ukuran" +oneline: "Menghapus batasan memori pada server bahasa TypeScript" +--- + +Untuk menghindari kemungkinan masalah pembengkakan memori saat bekerja dengan proyek JavaScript yang sangat besar, ada batas atas jumlah memori yang akan dialokasikan TypeScript. Mengaktifkan saran ini akan menghapus batas. \ No newline at end of file diff --git a/packages/tsconfig-reference/copy/id/options/disableSolutionSearching.md b/packages/tsconfig-reference/copy/id/options/disableSolutionSearching.md new file mode 100644 index 000000000000..58bfb7938ca1 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/disableSolutionSearching.md @@ -0,0 +1,8 @@ +--- +display: "Nonaktifkan Pencarian Solusi" +oneline: "Memilih proyek dari pemeriksaan referensi multi-proyek" +--- + +Saat bekerja dengan [proyek TypeScript komposit](/docs/handbook/project-references.html), opsi ini menyediakan cara untuk menyatakan bahwa Anda tidak ingin proyek disertakan saat menggunakan fitur seperti _find all reference_ atau _jump to definition_ di editor. + +Saran ini untuk sesuatu yang dapat Anda gunakan untuk meningkatkan daya tanggap dalam proyek komposit besar. \ No newline at end of file diff --git a/packages/tsconfig-reference/copy/id/options/disableSourceOfProjectReferenceRedirect.md b/packages/tsconfig-reference/copy/id/options/disableSourceOfProjectReferenceRedirect.md new file mode 100644 index 000000000000..212e9f692829 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/disableSourceOfProjectReferenceRedirect.md @@ -0,0 +1,7 @@ +--- +display: "Nonaktifkan Pengalihan Referensi Proyek Sumber" +oneline: "Gunakan berkas d.ts sebagai sumber kebenaran untuk perkakas antara batasan proyek gabungan" +--- + +Saat bekerja dengan [proyek TypeScript komposit](/docs/handbook/project-references.html), opsi ini menyediakan cara untuk menuju [kembali ke pra-3.7](/docs/handbook/release-notes/typescript-3-7.html#build-free-editing-with-project-references) perilaku di mana berkas d.ts digunakan sebagai batas antar modul. +Di 3.7, sumber kebenaran sekarang adalah berkas TypeScript Anda. diff --git a/packages/tsconfig-reference/copy/id/options/downlevelIteration.md b/packages/tsconfig-reference/copy/id/options/downlevelIteration.md new file mode 100644 index 000000000000..d044c9ecb7b7 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/downlevelIteration.md @@ -0,0 +1,75 @@ +--- +display: "Iterasi tingkat bawah" +oneline: "Menghasilkan JavaScript yang lebih sesuai, tetapi sangat rumit untuk objek iterasi" +--- + +_Downleveling_ adalah istilah TypeScript untuk mentranspilasi ke versi JavaScript yang lebih lama. +Saran ini untuk mengaktifkan dukungan implementasi yang lebih akurat tentang bagaimana JavaScript modern melakukan iterasi melalui konsep baru di _runtime_ JavaScript yang lebih lama. + +ECMAScript 6 menambahkan beberapa iterasi primitif baru: loop `for / of` (`for (el of arr)`), Array _spread_ (`[a, ...b]`), penyebaran argumen (`fn(...args)`), dan `Symbol.iterator`. +`--downlevelIteration` memungkinkan iterasi primitif ini digunakan secara lebih akurat dalam lingkungan ES5 jika ada implementasi `Symbol.iterator`. + +#### Contoh: Efek pada `for / of` + +Tanpa `downlevelIteration` aktif, loop `for / of` pada objek apa pun diturunkan levelnya menjadi loop `for` tradisional: + +```ts twoslash +// @target: ES5 +// @showEmit +const str = "Hello!"; +for (const s of str) { + console.log(s); +} +``` + +Hal ini sering kali diharapkan orang, tetapi tidak 100% sesuai dengan perilaku ECMAScript 6. +String tertentu, seperti emoji (😜), memiliki `.length` 2 (atau bahkan lebih!), Tetapi harus diiterasi sebagai 1 unit dalam loop `for-of`. +Lihat [postingan blog oleh Jonathan New](https://blog.jonnew.com/posts/poo-dot-length-equals-two) untuk penjelasan yang lebih lengkap. + +Jika `downlevelIteration` diaktifkan, TypeScript akan menggunakan fungsi bantuan yang memeriksa implementasi `Symbol.iterator` (baik _native_ maupun _polyfill_). +Jika implementasi ini hilang, Anda akan kembali ke iterasi berbasis _indeks_. + +```ts twoslash +// @target: ES5 +// @downlevelIteration +// @showEmit +const str = "Hello!"; +for (const s of str) { + console.log(s); +} +``` + +> > **Catatan:** memungkinkan `downlevelIteration` tidak meningkatkan kepatuhan jika `Symbol.iterator` tidak ada saat runtime. + +#### Contoh: Efek pada Array _Spreads_ + +ini adalah array _spread_: + +```js +// Buat array baru yang elemennya 1 diikuti dengan elemen arr2 +const arr = [1, ...arr2]; +``` + +Berdasarkan uraian tersebut, sepertinya mudah untuk menurunkan ke ES5: + +```js +// Sama kan? +const arr = [1].concat(arr2); +``` + +Namun, ini sangat berbeda dalam kasus tertentu yang jarang terjadi. +Misalnya, jika sebuah array memiliki "lubang" di dalamnya, indeks yang hilang akan membuat properti _own_ jika disebarkan, tetapi tidak akan jika dibuat menggunakan `concat`: + +```js +// Buatlah array dimana elemen '1' hilang +let missing = [0, , 1]; +let spreaded = [...missing]; +let concated = [].concat(missing); + +// benar +"1" in spreaded; +// salah +"1" in concated; +``` + +Seperti halnya dengan `for / of`, `downlevelIteration` akan menggunakan `Symbol.iterator` (jika ada) untuk meniru perilaku ES 6 dengan lebih akurat. diff --git a/packages/tsconfig-reference/copy/id/options/emitBOM.md b/packages/tsconfig-reference/copy/id/options/emitBOM.md new file mode 100644 index 000000000000..b46b463a8535 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/emitBOM.md @@ -0,0 +1,8 @@ +--- +display: "_Emit BOM_" +oneline: "Sertakan tanda urutan byte ke berkas keluaran" +--- + +Mengontrol apakah TypeScript akan menghasilkan [tanda urutan byte (_byte order mark_ - BOM)](https://wikipedia.org/wiki/Byte_order_mark) saat menulis berkas output. +Beberapa lingkungan _runtime_ memerlukan _BOM_ untuk menafsirkan berkas JavaScript dengan benar; yang lain mengharuskan itu tidak ada. +Nilai bawaan dari `false` umumnya paling baik kecuali Anda memiliki alasan untuk mengubahnya. diff --git a/packages/tsconfig-reference/copy/id/options/emitDeclarationOnly.md b/packages/tsconfig-reference/copy/id/options/emitDeclarationOnly.md new file mode 100644 index 000000000000..136109f4f223 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/emitDeclarationOnly.md @@ -0,0 +1,11 @@ +--- +display: "Menghasilkan Deklarasi Saja" +oneline: "Hanya mengeluarkan berkas d.ts dan bukan berkas .js" +--- + +_Hanya_ menghasilkan berkas `.d.ts`; jangan mengirimkan berkas `.js`. + +Pengaturan ini berguna dalam dua kasus: + +- Anda menggunakan _transpiler_ selain TypeScript untuk membuat JavaScript Anda. +- Anda menggunakan TypeScript hanya untuk menghasilkan berkas `d.ts` untuk konsumen Anda. diff --git a/packages/tsconfig-reference/copy/id/options/esModuleInterop.md b/packages/tsconfig-reference/copy/id/options/esModuleInterop.md new file mode 100644 index 000000000000..35001ed0cbf9 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/esModuleInterop.md @@ -0,0 +1,72 @@ +--- +display: "Interop Modul ES" +oneline: "Menghasilkan JS tambahan untuk memudahkan dukungan untuk mengimpor modul commonjs" +--- + +Secara bawaan (dengan `esModuleInterop` _false_ atau tidak disetel) TypeScript memperlakukan modul CommonJS/AMD/UMD mirip dengan modul ES6. Dalam melakukan ini, ada dua bagian tertentu yang ternyata merupakan asumsi yang salah: + +- Impor namespace seperti `import * as moment from "moment"` bertindak sama seperti `const moment = require("moment")` + +- Impor bawaan seperti `import moment as "moment"` berfungsi sama seperti `const moment = require("moment").default` + +Ketidakcocokan ini menyebabkan dua masalah berikut: + +- Spesifikasi modul ES6 menyatakan bahwa impor namespace (`import * as x`) hanya dapat menjadi objek, dengan memiliki TypeScript + memperlakukannya sama dengan `= require ("x")` maka TypeScript diizinkan untuk impor diperlakukan sebagai fungsi dan dapat dipanggil. Ini melanggar rekomendasi spesifikasi. + +- Meskipun akurat untuk spesifikasi modul ES6, sebagian besar pustaka dengan modul CommonJS/AMD/UMD tidak seketat implementasi TypeScript. + +Mengaktifkan `esModuleInterop` akan memperbaiki kedua masalah ini dalam kode yang ditranspilasi oleh TypeScript. Perubahan pertama perilaku di kompilator, yang kedua diperbaiki oleh dua fungsi pembantu baru yang menyediakan _shim_ untuk memastikan kompatibilitas dalam JavaScript yang dihasilkan: + +```ts +import * as fs from "fs"; +import _ from "lodash"; + +fs.readFileSync("file.txt", "utf8"); +_.chunk(["a", "b", "c", "d"], 2); +``` + +Dengan menonaktifkan `esModuleInterop`: + +```ts twoslash +// @noErrors +// @showEmit +// @esModuleInterop: false +// @module: commonjs +import * as fs from "fs"; +import _ from "lodash"; + +fs.readFileSync("file.txt", "utf8"); +_.chunk(["a", "b", "c", "d"], 2); +``` + +Dengan `esModuleInterop` disetel ke `true`: + +```ts twoslash +// @noErrors +// @showEmit +// @esModuleInterop +// @module: commonjs +import * as fs from "fs"; +import _ from "lodash"; + +fs.readFileSync("file.txt", "utf8"); +_.chunk(["a", "b", "c", "d"], 2); +``` + +_Catatan_: Anda dapat meminimalisir ukuran keluaran dengan mengaktifkan [`importHelpers`](#importHelpers): + +```ts twoslash +// @noErrors +// @showEmit +// @esModuleInterop +// @importHelpers +// @module: commonjs +import * as fs from "fs"; +import _ from "lodash"; + +fs.readFileSync("file.txt", "utf8"); +_.chunk(["a", "b", "c", "d"], 2); +``` + +Mengaktifkan `esModuleInterop` juga akan mengaktifkan [`allowSyntheticDefaultImports`](#allowSyntheticDefaultImports). diff --git a/packages/tsconfig-reference/copy/id/options/jsx.md b/packages/tsconfig-reference/copy/id/options/jsx.md new file mode 100644 index 000000000000..cc166295e88e --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/jsx.md @@ -0,0 +1,11 @@ +--- +display: "JSX" +oneline: "Mengatur bagaimana JSX dihasilkan" +--- + +Mengatur bagaimana konstruksi JSX dihasilkan di dalam file Javascript. +Ini hanya akan berpengaruh pada keluaran file JS yang dimulai di file `.tsx`. + +- `react`: Menghasilkan file `.js` dengan JSX yang diubah seperti pemanggilan `React.createElement` +- `preserve`: Menghasilkan file `.jsx` tanpa mengubah JSX +- `react-native`: Menghasilkan file `.jsx` tanpa mengubah JSX diff --git a/packages/tsconfig-reference/copy/id/options/jsxFactory.md b/packages/tsconfig-reference/copy/id/options/jsxFactory.md new file mode 100644 index 000000000000..7361ecc1546a --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/jsxFactory.md @@ -0,0 +1,9 @@ +--- +display: "JSX Factory" +oneline: "Mengatur fungsi yang dihasilkan oleh JSX" +--- + +Mengubah fungsi yang dipanggil pada file `.js` ketika melakukan kompilasi elemen-elemen JSX. +Perubahan yang paling umum adalah dengan menggunakan `"h"` atau `"preact.h"` dibandingkan penggunaan bawaan `"React.createElement"` jika menggunakan `preact`. + +Opsi ini dapat digunakan pada basis per file juga seperti halnya [Babel's `/** @jsx h */` directive](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#custom). diff --git a/packages/tsconfig-reference/copy/id/options/jsxFragmentFactory.md b/packages/tsconfig-reference/copy/id/options/jsxFragmentFactory.md new file mode 100644 index 000000000000..4def3cc57cbb --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/jsxFragmentFactory.md @@ -0,0 +1,54 @@ +--- +display: "jsxFragmentFactory" +oneline: "Menentukan pengidentifikasi fragmen JSX akan diubah seperti apa" +--- + +Menentukan fungsi penghasil fragmen JSX yang akan digunakan ketika menargetkan kompiler react JSX `jsxFactory` sudah ditentukan, misalnya seperti `Fragment`. + +Opsi ini dapat digunakan pada basis per file juga seperti halnya [Babel's `/** @jsxFrag h */` directive](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#fragments). + +Contoh dengan menggunakan TSConfig berikut ini: + +```json tsconfig +{ + "compilerOptions": { + "target": "esnext", + "module": "commonjs", + "jsx": "react", + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment" + } +} +``` + +TSX file berikut: + +```tsx +import { h, Fragment } from "preact"; + +const HelloWorld = () => ( + <> +
Hello
+ +); +``` + +Akan terlihat seperti: + +```tsx twoslash +// @showEmit +// @showEmittedFile: index.js +// @jsxFactory: h +// @jsxFragmentFactory: Fragment +// @noErrors +// @target: esnext +// @module: commonjs + +import { h, Fragment } from "preact"; + +const HelloWorld = () => ( + <> +
Hello
+ +); +``` diff --git a/packages/tsconfig-reference/copy/id/options/reactNamespace.md b/packages/tsconfig-reference/copy/id/options/reactNamespace.md new file mode 100644 index 000000000000..f18251ba353a --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/reactNamespace.md @@ -0,0 +1,6 @@ +--- +display: "React Namespace" +oneline: "Menentukan objek yang dipanggil oleh 'createElement' di JSX" +--- + +Gunakan [`--jsxFactory`](#jsxFactory) sebagai gantinya. Tentukan objek yang dipanggil oleh `createElement` ketika menargetkan `react` pada berkas TSX. diff --git a/packages/tsconfig-reference/copy/id/options/references.md b/packages/tsconfig-reference/copy/id/options/references.md new file mode 100644 index 000000000000..f7c7b6375ab3 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/references.md @@ -0,0 +1,9 @@ +--- +display: "Referensi" +oneline: "Menyediakan struktur untuk proyek komposit" +--- + +Referensi proyek adalah cara untuk menyusun program TypeScript Anda menjadi bagian-bagian yang lebih kecil. +Menggunakan Referensi Proyek dapat sangat meningkatkan waktu interaksi build dan editor, menerapkan pemisahan logika antar komponen, dan mengatur kode Anda dengan cara yang baru dan lebih baik. + +Anda dapat membaca lebih lanjut tentang bagaimana cara kerja referensi di bagian [Referensi Proyek](/docs/handbook/project-references.html) dari buku pegangan diff --git a/packages/tsconfig-reference/copy/id/options/removeComments.md b/packages/tsconfig-reference/copy/id/options/removeComments.md new file mode 100644 index 000000000000..6bd19afdc557 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/removeComments.md @@ -0,0 +1,33 @@ +--- +display: "Menghapus Komentar" +oneline: "Menghapus Komentar di TypeScript sehingga tidak muncul di Javascript" +--- + +Menghapus semua komentar pada berkas Typescript pada saat mengonversi ke berkas Javascript. Pengaturan bawaannya adalah `false` + +Sebagai contoh, ini adalah berkas TypeScript yang memiliki komentar JSDoc: + +```ts +/** Terjemahan dari 'Hello world' ke bahasa Indonesia */ +export const helloWorldID = "Halo Dunia"; +``` + +Ketika `removeComments` disetel ke `true`: + +```ts twoslash +// @showEmit +// @removeComments: true +/** Terjemahan dari 'Hello world' ke bahasa Indonesia */ +export const helloWorldID = "Halo Dunia"; +``` + +Tanpa menyetel `removeComments` atau menjadikannya sebagai `false`: + +```ts twoslash +// @showEmit +// @removeComments: false +/** Terjemahan dari 'Hello world' ke bahasa Indonesia */ +export const helloWorldID = "Halo Dunia"; +``` + +Artinya, komentar anda akan muncul di kode Javascript diff --git a/packages/tsconfig-reference/copy/id/options/resolveJsonModule.md b/packages/tsconfig-reference/copy/id/options/resolveJsonModule.md new file mode 100644 index 000000000000..97d6ef87f91c --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/resolveJsonModule.md @@ -0,0 +1,44 @@ +--- +display: "Menyelesaikan Module JSON" +oneline: "Memperbolehkan mengimpor berkas .json" +--- + +Memperbolehkan mengimpor modul dengan ekstensi '.json' merupakan praktik umum pada proyek node. +Ini termasuk membuat jenis untuk `import` berdasarkan bentuk JSON statis. + +TypeScript tidak mendukung penyelesaian berkas JSON secara bawaan: + +```ts twoslash +// @errors: 2732 +// @filename: settings.json +{ + "repo": "TypeScript", + "dry": false, + "debug": false +} +// @filename: index.ts +import settings from "./settings.json"; + +settings.debug === true; +settings.dry === 2; +``` + +Mengaktifkan opsi memungkinkan impor JSON, dan memvalidasi jenis dalam berkas JSON tersebut. + +```ts twoslash +// @errors: 2367 +// @resolveJsonModule +// @module: commonjs +// @moduleResolution: node +// @filename: settings.json +{ + "repo": "TypeScript", + "dry": false, + "debug": false +} +// @filename: index.ts +import settings from "./settings.json"; + +settings.debug === true; +settings.dry === 2; +``` diff --git a/packages/tsconfig-reference/copy/id/options/rootDir.md b/packages/tsconfig-reference/copy/id/options/rootDir.md new file mode 100644 index 000000000000..1a35c3a2e073 --- /dev/null +++ b/packages/tsconfig-reference/copy/id/options/rootDir.md @@ -0,0 +1,66 @@ +--- +display: "Root Dir" +oneline: "Menyetel direktori root di dalam berkas sumber Anda" +--- + +**Bawaan**: Jalur umum terpanjang dari semua berkas masukan non-deklarasi. Jika `composite` disetel, bawaannya adalah direktori yang berisi berkas `tsconfig.json`. + +Ketika TypeScript mengkompilasi berkas, ia mempertahankan struktur direktori yang sama pada direktori keluaran seperti struktur di direktori masukan. + +Misalnya, Anda memiliki beberapa berkas masukan: + +``` +MyProj +├── tsconfig.json +├── core +│ ├── a.ts +│ ├── b.ts +│ ├── sub +│ │ ├── c.ts +├── types.d.ts +``` + +Kesimpulan untuk `rootDir` adalah jalur umum terpanjang dari semua berkas masukan non-deklarasi, yang dalam hal ini adalah`core/`. + +Jika nilai `outDir` anda adalah `dist`, maka TypeScript akan membuat struktur direktori seperti ini: + +``` +MyProj +├── dist +│ ├── a.ts +│ ├── b.ts +│ ├── sub +│ │ ├── c.ts +``` + +Namun, anda mungkin mengharapkan `core` menjadi bagian dari struktur direktori keluaran. +Dengan menyetel `rootDir: "."` pada `tsconfig.json`, TypeScript akan menghasilkan struktur direktori seperti ini: + +``` +MyProj +├── dist +│ ├── core +│ │ ├── a.js +│ │ ├── b.js +│ │ ├── sub +│ │ │ ├── c.js +``` + +Yang terpenting, `rootDir` **tidak memengaruhi berkas mana yang menjadi bagian dari kompilasi**. +`rootDir` tidak memiliki hubungan dengan pengaturan `include`, `exclude`, atau `files` pada `tsconfig.json` + +Perhatikan bahwa TypeScript tidak akan pernah menulis berkas keluaran (_file output_) ke direktori di luar dari `outDir`, dan tidak akan pernah melewatkan pengeluaran berkas. +Karena alasan ini, `rootDir` mengharuskan semua berkas yang perlu dikeluarkan berada dibawah jalur `rootDir`. + +Misalnya, Anda memiliki struktur direktori seperti ini: + +``` +MyProj +├── tsconfig.json +├── core +│ ├── a.ts +│ ├── b.ts +├── helpers.ts +``` + +Ini akan menimbulkan galat ketika menentukan `rootDir` sebagai `core` dan `include` sebagai `*` karena ini membuat berkas (`helpers.ts`) yang perlu diletakkan di luar dari `outDir` (yaitu `../helpers.js`) diff --git a/packages/tsconfig-reference/copy/ko/options/baseUrl.md b/packages/tsconfig-reference/copy/ko/options/baseUrl.md new file mode 100644 index 000000000000..4a33215e6845 --- /dev/null +++ b/packages/tsconfig-reference/copy/ko/options/baseUrl.md @@ -0,0 +1,27 @@ +--- +display: "Base Url" +oneline: "Set a baseurl for relative module names" +--- + +절대 경로 참조가 아닌 모듈 이름을 해결하기 위한 기본 디렉터리를 설정할 수 있습니다. + +절대 경로로 해결하기 위한 루트 폴더를 정의할 수도 있습니다. 예를 들면, + +``` +baseUrl +├── ex.ts +├── hello +│ └── world.ts +└── tsconfig.json +``` + +이 프로젝트에서` "baseUrl": "./"`을 사용하면, TypeScript는`tsconfig.json`과 같은 폴더에서 시작하는 파일을 찾습니다. + +```ts +import { helloWorld } from "hello/world"; + +console.log(helloWorld); +``` + +항상 사용하는 `"../"` 또는 `"./"`같은 import에 질렸거나, 파일을 이동해서 변경해야 할 때, +사용할 수 있는 좋은 방법입니다. diff --git a/packages/tsconfig-reference/copy/ko/options/charset.md b/packages/tsconfig-reference/copy/ko/options/charset.md new file mode 100644 index 000000000000..987412227252 --- /dev/null +++ b/packages/tsconfig-reference/copy/ko/options/charset.md @@ -0,0 +1,7 @@ +--- +display: "Charset" +oneline: "Manually set the text encoding for reading files" +--- + +이전 버전의 TypeScript에서는, 디스크에서 텍스트 파일을 읽을 때 인코딩 방식을 제어했습니다. +현재 TypeScript는 UTF-8 인코딩을 전제로 합니다. 하지만 UTF-16 (BE 와 LE) 또는 UTF-8 BOMs도 정확하게 감지합니다. diff --git a/packages/tsconfig-reference/copy/pt/options/disableReferencedProjectLoad.md b/packages/tsconfig-reference/copy/pt/options/disableReferencedProjectLoad.md new file mode 100644 index 000000000000..6eae335f401d --- /dev/null +++ b/packages/tsconfig-reference/copy/pt/options/disableReferencedProjectLoad.md @@ -0,0 +1,9 @@ +--- +display: "Desabilitar o carregamento do projeto referenciado" +oneline: "Reduz o número de projetos carregados automaticamente pelo TypeScript" +--- + +Em aplicações Typescript de multi projetos, o TypeScript irá carregar todos os projetos disponíveis na memória com o objetivo de +fornecer resultados mais precisos para as respostas do editor que requerem um gráfico de conhecimento completo como 'Localizar todas as referências'. + +Se o seu projeto for grande, você pode utilizar a _flag_ `disableReferencedProjectLoad` para desabilitar o carregamento automático de todos os projetos. Com isso, os projetos serão carregados dinamicamente quando você abrir os arquivos através do seu editor. diff --git a/packages/tsconfig-reference/scripts/tsconfigRules.ts b/packages/tsconfig-reference/scripts/tsconfigRules.ts index d4fe7c1a84cb..e34991715f1f 100644 --- a/packages/tsconfig-reference/scripts/tsconfigRules.ts +++ b/packages/tsconfig-reference/scripts/tsconfigRules.ts @@ -193,7 +193,7 @@ export const allowedValues = { target: [ "`ES3` (default)", "`ES5`", - "`ES6`/`ES2015` (synonomous)", + "`ES6`/`ES2015` (synonymous)", "`ES7`/`ES2016`", "`ES2017`", "`ES2018`", diff --git a/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_0_phone.png b/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_0_phone.png index 49396df69530..f0be19e19030 100644 Binary files a/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_0_phone.png and b/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_0_phone.png differ diff --git a/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_1_tablet.png b/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_1_tablet.png index fb24c294a823..43368c139e74 100644 Binary files a/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_1_tablet.png and b/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_1_tablet.png differ diff --git a/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_2_computer.png b/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_2_computer.png index bda3cfb4a1c4..026a938f7490 100644 Binary files a/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_2_computer.png and b/packages/typescriptlang-org/_tests/backstop_data/bitmaps_reference/backstop_default_TSConfig_Example_0_viewport_2_computer.png differ diff --git a/packages/typescriptlang-org/gatsby-browser.js b/packages/typescriptlang-org/gatsby-browser.js index d3bcd3601199..d42e93785492 100644 --- a/packages/typescriptlang-org/gatsby-browser.js +++ b/packages/typescriptlang-org/gatsby-browser.js @@ -37,6 +37,7 @@ exports.onRouteUpdate = ({ location, prevLocation }) => { uri: locationWithoutPlaygroundCode, refUri: referrerWithoutPlaygroundCode, prev: previousLocationWithoutPlaygroundCode, + lang: document.documentElement.lang, visitedPlayground: hasLocalStorage && localStorage.getItem("sandbox-history") !== null, }) diff --git a/packages/typescriptlang-org/lib/bootup/ingestion/createPlaygroundExamplePages.ts b/packages/typescriptlang-org/lib/bootup/ingestion/createPlaygroundExamplePages.ts index a7c3e44aa9c2..ac841f8948b7 100644 --- a/packages/typescriptlang-org/lib/bootup/ingestion/createPlaygroundExamplePages.ts +++ b/packages/typescriptlang-org/lib/bootup/ingestion/createPlaygroundExamplePages.ts @@ -50,11 +50,7 @@ export const createPlaygroundExamplePages = async ( .replace(/\+/g, "-") const language = rPath.split("/")[0] - const postLangPath = rPath - .split("/") - .slice(1) - .map(idize) - .join("/") + const postLangPath = rPath.split("/").slice(1).map(idize).join("/") const langPrefix = language === "en" ? "" : language const newPagePath = langPrefix + "/play/" + postLangPath @@ -64,14 +60,11 @@ export const createPlaygroundExamplePages = async ( const exampleCodePath = path.join(appRoot, "playground-examples", "copy", rPath) const code = fs.readFileSync(exampleCodePath, "utf8") - const id = postLangPath - .split("/") - .slice(-1)[0] - .split(".")[0] + const id = postLangPath.split("/").slice(-1)[0].split(".")[0] const { inlineTitle, compilerSettings } = getCompilerDetailsFromCode(code) createPage({ - path: newPagePath, + path: newPagePath + ".html", component: playPage, context: { name, @@ -106,11 +99,11 @@ const getCompilerDetailsFromCode = (contents: string) => { if (contents.startsWith("//// {")) { // convert windows newlines to linux new lines - const preJSON = contents.replace(/\r\n/g, "\n").split("//// {")[1].split("}\n")[0] - contents = contents - .split("\n") - .slice(1) - .join("\n") + const preJSON = contents + .replace(/\r\n/g, "\n") + .split("//// {")[1] + .split("}\n")[0] + contents = contents.split("\n").slice(1).join("\n") const code = "({" + preJSON + "})" try { diff --git a/packages/typescriptlang-org/scripts/makeMarkdownOfTranslations.js b/packages/typescriptlang-org/scripts/makeMarkdownOfTranslations.js index 65ebeec8b846..e84a1704f9b7 100644 --- a/packages/typescriptlang-org/scripts/makeMarkdownOfTranslations.js +++ b/packages/typescriptlang-org/scripts/makeMarkdownOfTranslations.js @@ -54,8 +54,11 @@ const getAllTODOFiles = lang => { return all } +let totalDone = 0 +let totalTodo = 0 + const toMarkdown = files => { - const md = [] + const md = [""] const markdownLink = (f, done) => { const name = basename(f) @@ -69,8 +72,8 @@ const toMarkdown = files => { const todo = files[section].todo const done = files[section].done - md.push("\n\n## " + section + "\n\n") - + md.push("\n\n## " + section + "\n") + md.push(`Done: ${done.length}, TODO: ${todo.length}.\n\n`) done.forEach(f => { md.push(markdownLink(f, true)) }) @@ -78,8 +81,12 @@ const toMarkdown = files => { todo.forEach(f => { md.push(markdownLink(f)) }) + + totalDone += done.length + totalTodo += todo.length }) + md[0] = `For this language there are ${totalDone} translated files, with ${totalTodo} TODO.\n\n` return md.join("\n") } diff --git a/packages/typescriptlang-org/scripts/updateGitHubTranslationIssues.ts b/packages/typescriptlang-org/scripts/updateGitHubTranslationIssues.ts index e9e4e7157616..17f47ca04025 100644 --- a/packages/typescriptlang-org/scripts/updateGitHubTranslationIssues.ts +++ b/packages/typescriptlang-org/scripts/updateGitHubTranslationIssues.ts @@ -13,6 +13,7 @@ const languages = { zh: 296, ko: 910, id: 938, + uk: 1149, } const go = async () => { diff --git a/packages/typescriptlang-org/src/components/HeadSEO.tsx b/packages/typescriptlang-org/src/components/HeadSEO.tsx index c3ab6656f07b..e25cf847c247 100644 --- a/packages/typescriptlang-org/src/components/HeadSEO.tsx +++ b/packages/typescriptlang-org/src/components/HeadSEO.tsx @@ -1,5 +1,4 @@ import * as React from "react" -import { withPrefix } from "gatsby" import { Helmet } from "react-helmet"; @@ -18,6 +17,12 @@ export const HeadSEO = (props: SeoProps) => { "twitter:site": "typescriptlang", } + // Skip indexing on the staging site + const staging = process && process.env && process.env.TYPESCRIPT_SITE_STAGING + if (staging) { + ogTags["robots"] = "noindex" + } + // do we want localized pages to be the english version? //{seo.url && } diff --git a/packages/typescriptlang-org/src/components/layout/CookieBanner.tsx b/packages/typescriptlang-org/src/components/layout/CookieBanner.tsx index 9aa39342e5ab..fbc169ff6fc5 100644 --- a/packages/typescriptlang-org/src/components/layout/CookieBanner.tsx +++ b/packages/typescriptlang-org/src/components/layout/CookieBanner.tsx @@ -20,6 +20,9 @@ export const CookieBanner = (props: { lang: string }) => { const verboseCookieLogging = () => { let siteConsent + // If they ship a bad build of the cookie banner, then even though the script is fully there + // the global symbols won't be + if (!WcpConsent) return WcpConsent.init("en-US", "cookie-banner", (err, _siteConsent) => { if (err) { @@ -30,6 +33,7 @@ export const CookieBanner = (props: { lang: string }) => { } }, onConsentChanged); + function onConsentChanged(newConsent: any) { if (newConsent.isConsentRequired) { // newConsent.manageConsent(); diff --git a/packages/typescriptlang-org/src/components/layout/Sidebar.scss b/packages/typescriptlang-org/src/components/layout/Sidebar.scss index e48090d296ab..3f7e26cd0e32 100644 --- a/packages/typescriptlang-org/src/components/layout/Sidebar.scss +++ b/packages/typescriptlang-org/src/components/layout/Sidebar.scss @@ -16,12 +16,6 @@ nav#sidebar { margin: 0; padding: 0; - @media (min-width: $screen-sm) { - max-height: calc(100vh - 10px); - overflow-y: auto; - overflow-x: hidden; - } - li { // Mostly stuff for all of the links list-style: none; @@ -157,6 +151,15 @@ nav#sidebar { } } } + + // Only set max-height and overflow rules for direct ul children to prevent scrolling in subnav uls + & > ul { + @media (min-width: $screen-sm) { + max-height: calc(100vh - 10px); + overflow-y: auto; + overflow-x: hidden; + } + } } @media (max-width: $screen-sm) { diff --git a/packages/typescriptlang-org/src/lib/documentationNavigation.ts b/packages/typescriptlang-org/src/lib/documentationNavigation.ts index 856b19f20e25..1d63005a4328 100644 --- a/packages/typescriptlang-org/src/lib/documentationNavigation.ts +++ b/packages/typescriptlang-org/src/lib/documentationNavigation.ts @@ -611,11 +611,17 @@ export function getDocumentationNavForLanguage( items: [ { - title: "tsconfig.json", - id: "7tsconfig.json", + title: "What is a tsconfig.json", + id: "7what-is-a-tsconfig.json", permalink: "/docs/handbook/tsconfig-json.html", oneline: "Learn about how a TSConfig works", }, + { + title: "Compiler Options in MSBuild", + id: "7compiler-options-in-msbuild", + permalink: "/docs/handbook/compiler-options-in-msbuild.html", + oneline: "Which compiler options are available in MSBuild projects.", + }, { title: "TSConfig Reference", id: "7tsconfig-reference", @@ -623,11 +629,11 @@ export function getDocumentationNavForLanguage( oneline: "The page covering every TSConfig option", }, { - title: "Compiler Options", - id: "7compiler-options", + title: "tsc CLI Options", + id: "7tsc-cli-options", permalink: "/docs/handbook/compiler-options.html", oneline: - "A very high-level overview of the compiler options in TypeScript", + "A very high-level overview of the CLI compiler options for tsc", }, { title: "Project References", @@ -635,12 +641,6 @@ export function getDocumentationNavForLanguage( permalink: "/docs/handbook/project-references.html", oneline: "How to split up a large TypeScript project", }, - { - title: "Compiler Options in MSBuild", - id: "7compiler-options-in-msbuild", - permalink: "/docs/handbook/compiler-options-in-msbuild.html", - oneline: "Which compiler options are available in MSBuild projects.", - }, { title: "Integrating with Build Tools", id: "7integrating-with-build-tools", @@ -1324,11 +1324,17 @@ export function getDocumentationNavForLanguage( items: [ { - title: "tsconfig.json", - id: "7tsconfig.json", + title: "What is a tsconfig.json", + id: "7what-is-a-tsconfig.json", permalink: "/docs/handbook/tsconfig-json.html", oneline: "Learn about how a TSConfig works", }, + { + title: "Compiler Options in MSBuild", + id: "7compiler-options-in-msbuild", + permalink: "/docs/handbook/compiler-options-in-msbuild.html", + oneline: "Which compiler options are available in MSBuild projects.", + }, { title: "TSConfig Reference", id: "7tsconfig-reference", @@ -1336,11 +1342,11 @@ export function getDocumentationNavForLanguage( oneline: "The page covering every TSConfig option", }, { - title: "Compiler Options", - id: "7compiler-options", + title: "tsc CLI Options", + id: "7tsc-cli-options", permalink: "/docs/handbook/compiler-options.html", oneline: - "A very high-level overview of the compiler options in TypeScript", + "A very high-level overview of the CLI compiler options for tsc", }, { title: "Project References", @@ -1348,12 +1354,6 @@ export function getDocumentationNavForLanguage( permalink: "/docs/handbook/project-references.html", oneline: "How to split up a large TypeScript project", }, - { - title: "Compiler Options in MSBuild", - id: "7compiler-options-in-msbuild", - permalink: "/docs/handbook/compiler-options-in-msbuild.html", - oneline: "Which compiler options are available in MSBuild projects.", - }, { title: "Integrating with Build Tools", id: "7integrating-with-build-tools", @@ -1576,10 +1576,10 @@ export function getDocumentationNavForLanguage( oneline: "Types which are globally included in TypeScript", }, { - title: "Decorators", - id: "2decorators", - permalink: "/docs/handbook/decorators.html", - oneline: "TypeScript Decorators overview", + title: "Decoradores", + id: "2decoradores", + permalink: "/pt/docs/handbook/Decorators.html", + oneline: "Visão geral dos Decoradores no TypeScript", }, { title: "Declaration Merging", @@ -1620,8 +1620,8 @@ export function getDocumentationNavForLanguage( { title: "Namespaces", id: "2namespaces", - permalink: "/docs/handbook/namespaces.html", - oneline: "How TypeScript namespaces work", + permalink: "/pt/docs/handbook/namespaces.html", + oneline: "Como funcionam os Namespaces no TypeScript", }, { title: "Namespaces and Modules", @@ -1631,10 +1631,10 @@ export function getDocumentationNavForLanguage( "How to organize code in TypeScript via modules or namespaces", }, { - title: "Symbols", - id: "2symbols", - permalink: "/docs/handbook/symbols.html", - oneline: "Using the JavaScript Symbol primitive in TypeScript", + title: "Símbolos (Symbols)", + id: "2símbolos-(symbols)", + permalink: "/pt/docs/handbook/symbols.html", + oneline: "Usando o símbolo primitivo do JavaScript no TypeScript", }, { title: "Triple-Slash Directives", @@ -2037,11 +2037,17 @@ export function getDocumentationNavForLanguage( items: [ { - title: "tsconfig.json", - id: "7tsconfig.json", + title: "What is a tsconfig.json", + id: "7what-is-a-tsconfig.json", permalink: "/docs/handbook/tsconfig-json.html", oneline: "Learn about how a TSConfig works", }, + { + title: "Compiler Options in MSBuild", + id: "7compiler-options-in-msbuild", + permalink: "/docs/handbook/compiler-options-in-msbuild.html", + oneline: "Which compiler options are available in MSBuild projects.", + }, { title: "TSConfig Reference", id: "7tsconfig-reference", @@ -2049,11 +2055,11 @@ export function getDocumentationNavForLanguage( oneline: "The page covering every TSConfig option", }, { - title: "Compiler Options", - id: "7compiler-options", + title: "tsc CLI Options", + id: "7tsc-cli-options", permalink: "/docs/handbook/compiler-options.html", oneline: - "A very high-level overview of the compiler options in TypeScript", + "A very high-level overview of the CLI compiler options for tsc", }, { title: "Project References", @@ -2061,12 +2067,6 @@ export function getDocumentationNavForLanguage( permalink: "/docs/handbook/project-references.html", oneline: "How to split up a large TypeScript project", }, - { - title: "Compiler Options in MSBuild", - id: "7compiler-options-in-msbuild", - permalink: "/docs/handbook/compiler-options-in-msbuild.html", - oneline: "Which compiler options are available in MSBuild projects.", - }, { title: "Integrating with Build Tools", id: "7integrating-with-build-tools", @@ -2750,11 +2750,17 @@ export function getDocumentationNavForLanguage( items: [ { - title: "tsconfig.json", - id: "7tsconfig.json", + title: "What is a tsconfig.json", + id: "7what-is-a-tsconfig.json", permalink: "/docs/handbook/tsconfig-json.html", oneline: "Learn about how a TSConfig works", }, + { + title: "Compiler Options in MSBuild", + id: "7compiler-options-in-msbuild", + permalink: "/docs/handbook/compiler-options-in-msbuild.html", + oneline: "Which compiler options are available in MSBuild projects.", + }, { title: "TSConfig Reference", id: "7tsconfig-reference", @@ -2762,11 +2768,11 @@ export function getDocumentationNavForLanguage( oneline: "The page covering every TSConfig option", }, { - title: "Compiler Options", - id: "7compiler-options", + title: "tsc CLI Options", + id: "7tsc-cli-options", permalink: "/docs/handbook/compiler-options.html", oneline: - "A very high-level overview of the compiler options in TypeScript", + "A very high-level overview of the CLI compiler options for tsc", }, { title: "Project References", @@ -2774,12 +2780,6 @@ export function getDocumentationNavForLanguage( permalink: "/docs/handbook/project-references.html", oneline: "How to split up a large TypeScript project", }, - { - title: "Compiler Options in MSBuild", - id: "7compiler-options-in-msbuild", - permalink: "/docs/handbook/compiler-options-in-msbuild.html", - oneline: "Which compiler options are available in MSBuild projects.", - }, { title: "Integrating with Build Tools", id: "7integrating-with-build-tools", diff --git a/packages/typescriptlang-org/src/templates/pages/why-create-typescript.tsx b/packages/typescriptlang-org/src/templates/pages/why-create-typescript.tsx index 3924867e41fd..99aec8561fd9 100644 --- a/packages/typescriptlang-org/src/templates/pages/why-create-typescript.tsx +++ b/packages/typescriptlang-org/src/templates/pages/why-create-typescript.tsx @@ -140,7 +140,7 @@ used in your code, a bit like Java.

{`
 var name: string = "Danger"
-console.log("Hello, " + danger)
+console.log("Hello, " + name)
 `.trim()}

This extra : string allow the reader to be certain that name will only be a string. Annotating your variables diff --git a/packages/typescriptlang-org/src/templates/play-example.tsx b/packages/typescriptlang-org/src/templates/play-example.tsx index f91a21f80974..28ba241fae55 100644 --- a/packages/typescriptlang-org/src/templates/play-example.tsx +++ b/packages/typescriptlang-org/src/templates/play-example.tsx @@ -34,7 +34,8 @@ const Play = (props: Props) => { return ( -

+
+

{props.pageContext.title}

diff --git a/packages/typescriptlang-org/src/templates/play.tsx b/packages/typescriptlang-org/src/templates/play.tsx index 67a1700ff776..9f7f1406fca5 100644 --- a/packages/typescriptlang-org/src/templates/play.tsx +++ b/packages/typescriptlang-org/src/templates/play.tsx @@ -79,13 +79,33 @@ const Play: React.FC = (props) => { tsVersionParam = nightlyJSON.version } - const tsVersion = tsVersionParam || playgroundReleases.versions.sort().pop() + // Somehow people keep trying -insiders urls instead of -dev - maybe some tooling I don't know? + if (tsVersionParam && tsVersionParam.includes("-insiders.")) { + tsVersionParam = tsVersionParam.replace("-insiders.", "-dev.") + } + + const latestRelease = [...playgroundReleases.versions].sort().pop() + const tsVersion = tsVersionParam || latestRelease // Because we can reach to localhost ports from the site, it's possible for the locally built compiler to // be hosted and to power the editor with a bit of elbow grease. const useLocalCompiler = tsVersion === "dev" const urlForMonaco = useLocalCompiler ? "http://localhost:5615/dev/vs" : `https://typescript.azureedge.net/cdn/${tsVersion}/monaco/min/vs` + // Make a quick HEAD call for the main monaco editor for this version of TS, if it + // bails then give a useful error message and bail. + const nightlyLookup = await fetch(urlForMonaco + "/editor/editor.main.js", { method: "HEAD" }) + if (!nightlyLookup.ok) { + document.querySelectorAll(".lds-grid div").forEach(div => { + div.style.backgroundColor = "red" + div.style.animation = "" + div.style.webkitAnimation = "" + }) + + document.getElementById("loading-message")!.innerHTML = `This version of TypeScript (${tsVersion?.replace("<", "-")})
has not been prepared for the Playground

Try ${latestRelease} or Nightly` + return + } + // @ts-ignore const re: any = global.require re.config({ diff --git a/packages/typescriptlang-org/src/templates/tsconfigReference.tsx b/packages/typescriptlang-org/src/templates/tsconfigReference.tsx index 4416c903070c..00f9a58e29ff 100644 --- a/packages/typescriptlang-org/src/templates/tsconfigReference.tsx +++ b/packages/typescriptlang-org/src/templates/tsconfigReference.tsx @@ -74,7 +74,7 @@ const TSConfigReferenceTemplateComponent = (props) => { return ( -
+