From a1ca06febba972f4361713bba10fef4d0c114c01 Mon Sep 17 00:00:00 2001 From: Orta Therox Date: Mon, 26 Aug 2019 18:11:57 -0300 Subject: [PATCH] More examples --- .../Advanced Meta-Types/Conditional Types.ts | 0 .../TypeScript/Meta-Types/Mapped Types.ts | 0 .../Primitives/Built-in Utility Types.ts | 0 Examples/TypeScript/Primitives/Literals.ts | 0 Examples/TypeScript/Primitives/Unions.ts | 0 .../External APIs/TypeScript + Deno.ts | 0 .../External APIs/TypeScript + Node.ts | 0 .../External APIs/TypeScript + React.tsx | 0 .../External APIs/TypeScript + Web.ts | 0 .../External APIs/TypeScript + WebGL.ts | 0 .../Function Chaining.ts | 0 .../Generic Functions.ts | 0 .../Typing Functions.ts | 0 .../Helping with JavaScript/Errors.ts | 0 .../Helping with JavaScript/Quick Fixes.ts | 0 .../Helping with JavaScript/Warnings.ts | 0 .../JavaScript Essentials/Code Flow.ts | 0 .../JavaScript Essentials/Functions.ts | 0 .../JavaScript Essentials/Hello World.ts | 0 .../Objects and Arrays.ts | 0 .../Modern JavaScript/Async:Await.ts | 0 .../Modern JavaScript/Immutability.ts | 0 .../Modern JavaScript/Import:Export.ts | 0 .../Modern JavaScript/JSDoc Support.ts | 0 .../Working With Classes/Classes 101.ts | 0 .../Working With Classes/Generic Classes.ts | 0 .../JavaScript/Working With Classes/Mixins.ts | 0 .../JavaScript/Working With Classes/This.ts | 23 +-- .../Advanced Meta-Types/Conditional Types.ts | 103 ++++++++++++++ .../Advanced Meta-Types/Discriminate Types.ts | 0 .../TypeScript/Language Extensions/Enums.ts | 0 .../Types vs Interfaces.ts | 0 Examples/en/TypeScript/Language/Soundness.ts | 23 +++ .../Language}/Type Widening:Narrowing.ts | 0 .../TypeScript/Meta-Types/Indexed Types.ts | 0 .../en/TypeScript/Meta-Types/Mapped Types.ts | 57 ++++++++ .../TypeScript/Meta-Types/Nominal Typing.ts | 0 Examples/en/TypeScript/Primitives/Any.ts | 33 +++++ Examples/en/TypeScript/Primitives/Literals.ts | 69 +++++++++ .../Union and Intersection Types.ts | 0 .../Primitives}/Unknown and Never.ts | 19 ++- .../Type Primitives/Built-in Utility Types.ts | 131 ++++++++++++++++++ .../Type Primitives}/Nullable Types.ts | 0 .../TypeScript/Type Primitives}/Tuples.ts | 0 Examples/scripts/generateTOC.js | 2 +- 45 files changed, 449 insertions(+), 11 deletions(-) delete mode 100644 Examples/TypeScript/Advanced Meta-Types/Conditional Types.ts delete mode 100644 Examples/TypeScript/Meta-Types/Mapped Types.ts delete mode 100644 Examples/TypeScript/Primitives/Built-in Utility Types.ts delete mode 100644 Examples/TypeScript/Primitives/Literals.ts delete mode 100644 Examples/TypeScript/Primitives/Unions.ts rename Examples/{ => en}/JavaScript/External APIs/TypeScript + Deno.ts (100%) rename Examples/{ => en}/JavaScript/External APIs/TypeScript + Node.ts (100%) rename Examples/{ => en}/JavaScript/External APIs/TypeScript + React.tsx (100%) rename Examples/{ => en}/JavaScript/External APIs/TypeScript + Web.ts (100%) rename Examples/{ => en}/JavaScript/External APIs/TypeScript + WebGL.ts (100%) rename Examples/{ => en}/JavaScript/Functions with JavaScript/Function Chaining.ts (100%) rename Examples/{ => en}/JavaScript/Functions with JavaScript/Generic Functions.ts (100%) rename Examples/{ => en}/JavaScript/Functions with JavaScript/Typing Functions.ts (100%) rename Examples/{ => en}/JavaScript/Helping with JavaScript/Errors.ts (100%) rename Examples/{ => en}/JavaScript/Helping with JavaScript/Quick Fixes.ts (100%) rename Examples/{ => en}/JavaScript/Helping with JavaScript/Warnings.ts (100%) rename Examples/{ => en}/JavaScript/JavaScript Essentials/Code Flow.ts (100%) rename Examples/{ => en}/JavaScript/JavaScript Essentials/Functions.ts (100%) rename Examples/{ => en}/JavaScript/JavaScript Essentials/Hello World.ts (100%) rename Examples/{ => en}/JavaScript/JavaScript Essentials/Objects and Arrays.ts (100%) rename Examples/{ => en}/JavaScript/Modern JavaScript/Async:Await.ts (100%) rename Examples/{ => en}/JavaScript/Modern JavaScript/Immutability.ts (100%) rename Examples/{ => en}/JavaScript/Modern JavaScript/Import:Export.ts (100%) rename Examples/{ => en}/JavaScript/Modern JavaScript/JSDoc Support.ts (100%) rename Examples/{ => en}/JavaScript/Working With Classes/Classes 101.ts (100%) rename Examples/{ => en}/JavaScript/Working With Classes/Generic Classes.ts (100%) rename Examples/{ => en}/JavaScript/Working With Classes/Mixins.ts (100%) rename Examples/{ => en}/JavaScript/Working With Classes/This.ts (78%) create mode 100644 Examples/en/TypeScript/Advanced Meta-Types/Conditional Types.ts rename Examples/{ => en}/TypeScript/Advanced Meta-Types/Discriminate Types.ts (100%) rename Examples/{ => en}/TypeScript/Language Extensions/Enums.ts (100%) rename Examples/{TypeScript/Language Extensions Two => en/TypeScript/Language Extensions}/Types vs Interfaces.ts (100%) create mode 100644 Examples/en/TypeScript/Language/Soundness.ts rename Examples/{TypeScript/Primitives => en/TypeScript/Language}/Type Widening:Narrowing.ts (100%) rename Examples/{ => en}/TypeScript/Meta-Types/Indexed Types.ts (100%) create mode 100644 Examples/en/TypeScript/Meta-Types/Mapped Types.ts rename Examples/{ => en}/TypeScript/Meta-Types/Nominal Typing.ts (100%) create mode 100644 Examples/en/TypeScript/Primitives/Any.ts create mode 100644 Examples/en/TypeScript/Primitives/Literals.ts rename Examples/{TypeScript/Advanced Meta-Types => en/TypeScript/Primitives}/Union and Intersection Types.ts (100%) rename Examples/{TypeScript/Language Extensions => en/TypeScript/Primitives}/Unknown and Never.ts (88%) create mode 100644 Examples/en/TypeScript/Type Primitives/Built-in Utility Types.ts rename Examples/{TypeScript/Language Extensions => en/TypeScript/Type Primitives}/Nullable Types.ts (100%) rename Examples/{TypeScript/Language Extensions => en/TypeScript/Type Primitives}/Tuples.ts (100%) diff --git a/Examples/TypeScript/Advanced Meta-Types/Conditional Types.ts b/Examples/TypeScript/Advanced Meta-Types/Conditional Types.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/Examples/TypeScript/Meta-Types/Mapped Types.ts b/Examples/TypeScript/Meta-Types/Mapped Types.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/Examples/TypeScript/Primitives/Built-in Utility Types.ts b/Examples/TypeScript/Primitives/Built-in Utility Types.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/Examples/TypeScript/Primitives/Literals.ts b/Examples/TypeScript/Primitives/Literals.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/Examples/TypeScript/Primitives/Unions.ts b/Examples/TypeScript/Primitives/Unions.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/Examples/JavaScript/External APIs/TypeScript + Deno.ts b/Examples/en/JavaScript/External APIs/TypeScript + Deno.ts similarity index 100% rename from Examples/JavaScript/External APIs/TypeScript + Deno.ts rename to Examples/en/JavaScript/External APIs/TypeScript + Deno.ts diff --git a/Examples/JavaScript/External APIs/TypeScript + Node.ts b/Examples/en/JavaScript/External APIs/TypeScript + Node.ts similarity index 100% rename from Examples/JavaScript/External APIs/TypeScript + Node.ts rename to Examples/en/JavaScript/External APIs/TypeScript + Node.ts diff --git a/Examples/JavaScript/External APIs/TypeScript + React.tsx b/Examples/en/JavaScript/External APIs/TypeScript + React.tsx similarity index 100% rename from Examples/JavaScript/External APIs/TypeScript + React.tsx rename to Examples/en/JavaScript/External APIs/TypeScript + React.tsx diff --git a/Examples/JavaScript/External APIs/TypeScript + Web.ts b/Examples/en/JavaScript/External APIs/TypeScript + Web.ts similarity index 100% rename from Examples/JavaScript/External APIs/TypeScript + Web.ts rename to Examples/en/JavaScript/External APIs/TypeScript + Web.ts diff --git a/Examples/JavaScript/External APIs/TypeScript + WebGL.ts b/Examples/en/JavaScript/External APIs/TypeScript + WebGL.ts similarity index 100% rename from Examples/JavaScript/External APIs/TypeScript + WebGL.ts rename to Examples/en/JavaScript/External APIs/TypeScript + WebGL.ts diff --git a/Examples/JavaScript/Functions with JavaScript/Function Chaining.ts b/Examples/en/JavaScript/Functions with JavaScript/Function Chaining.ts similarity index 100% rename from Examples/JavaScript/Functions with JavaScript/Function Chaining.ts rename to Examples/en/JavaScript/Functions with JavaScript/Function Chaining.ts diff --git a/Examples/JavaScript/Functions with JavaScript/Generic Functions.ts b/Examples/en/JavaScript/Functions with JavaScript/Generic Functions.ts similarity index 100% rename from Examples/JavaScript/Functions with JavaScript/Generic Functions.ts rename to Examples/en/JavaScript/Functions with JavaScript/Generic Functions.ts diff --git a/Examples/JavaScript/Functions with JavaScript/Typing Functions.ts b/Examples/en/JavaScript/Functions with JavaScript/Typing Functions.ts similarity index 100% rename from Examples/JavaScript/Functions with JavaScript/Typing Functions.ts rename to Examples/en/JavaScript/Functions with JavaScript/Typing Functions.ts diff --git a/Examples/JavaScript/Helping with JavaScript/Errors.ts b/Examples/en/JavaScript/Helping with JavaScript/Errors.ts similarity index 100% rename from Examples/JavaScript/Helping with JavaScript/Errors.ts rename to Examples/en/JavaScript/Helping with JavaScript/Errors.ts diff --git a/Examples/JavaScript/Helping with JavaScript/Quick Fixes.ts b/Examples/en/JavaScript/Helping with JavaScript/Quick Fixes.ts similarity index 100% rename from Examples/JavaScript/Helping with JavaScript/Quick Fixes.ts rename to Examples/en/JavaScript/Helping with JavaScript/Quick Fixes.ts diff --git a/Examples/JavaScript/Helping with JavaScript/Warnings.ts b/Examples/en/JavaScript/Helping with JavaScript/Warnings.ts similarity index 100% rename from Examples/JavaScript/Helping with JavaScript/Warnings.ts rename to Examples/en/JavaScript/Helping with JavaScript/Warnings.ts diff --git a/Examples/JavaScript/JavaScript Essentials/Code Flow.ts b/Examples/en/JavaScript/JavaScript Essentials/Code Flow.ts similarity index 100% rename from Examples/JavaScript/JavaScript Essentials/Code Flow.ts rename to Examples/en/JavaScript/JavaScript Essentials/Code Flow.ts diff --git a/Examples/JavaScript/JavaScript Essentials/Functions.ts b/Examples/en/JavaScript/JavaScript Essentials/Functions.ts similarity index 100% rename from Examples/JavaScript/JavaScript Essentials/Functions.ts rename to Examples/en/JavaScript/JavaScript Essentials/Functions.ts diff --git a/Examples/JavaScript/JavaScript Essentials/Hello World.ts b/Examples/en/JavaScript/JavaScript Essentials/Hello World.ts similarity index 100% rename from Examples/JavaScript/JavaScript Essentials/Hello World.ts rename to Examples/en/JavaScript/JavaScript Essentials/Hello World.ts diff --git a/Examples/JavaScript/JavaScript Essentials/Objects and Arrays.ts b/Examples/en/JavaScript/JavaScript Essentials/Objects and Arrays.ts similarity index 100% rename from Examples/JavaScript/JavaScript Essentials/Objects and Arrays.ts rename to Examples/en/JavaScript/JavaScript Essentials/Objects and Arrays.ts diff --git a/Examples/JavaScript/Modern JavaScript/Async:Await.ts b/Examples/en/JavaScript/Modern JavaScript/Async:Await.ts similarity index 100% rename from Examples/JavaScript/Modern JavaScript/Async:Await.ts rename to Examples/en/JavaScript/Modern JavaScript/Async:Await.ts diff --git a/Examples/JavaScript/Modern JavaScript/Immutability.ts b/Examples/en/JavaScript/Modern JavaScript/Immutability.ts similarity index 100% rename from Examples/JavaScript/Modern JavaScript/Immutability.ts rename to Examples/en/JavaScript/Modern JavaScript/Immutability.ts diff --git a/Examples/JavaScript/Modern JavaScript/Import:Export.ts b/Examples/en/JavaScript/Modern JavaScript/Import:Export.ts similarity index 100% rename from Examples/JavaScript/Modern JavaScript/Import:Export.ts rename to Examples/en/JavaScript/Modern JavaScript/Import:Export.ts diff --git a/Examples/JavaScript/Modern JavaScript/JSDoc Support.ts b/Examples/en/JavaScript/Modern JavaScript/JSDoc Support.ts similarity index 100% rename from Examples/JavaScript/Modern JavaScript/JSDoc Support.ts rename to Examples/en/JavaScript/Modern JavaScript/JSDoc Support.ts diff --git a/Examples/JavaScript/Working With Classes/Classes 101.ts b/Examples/en/JavaScript/Working With Classes/Classes 101.ts similarity index 100% rename from Examples/JavaScript/Working With Classes/Classes 101.ts rename to Examples/en/JavaScript/Working With Classes/Classes 101.ts diff --git a/Examples/JavaScript/Working With Classes/Generic Classes.ts b/Examples/en/JavaScript/Working With Classes/Generic Classes.ts similarity index 100% rename from Examples/JavaScript/Working With Classes/Generic Classes.ts rename to Examples/en/JavaScript/Working With Classes/Generic Classes.ts diff --git a/Examples/JavaScript/Working With Classes/Mixins.ts b/Examples/en/JavaScript/Working With Classes/Mixins.ts similarity index 100% rename from Examples/JavaScript/Working With Classes/Mixins.ts rename to Examples/en/JavaScript/Working With Classes/Mixins.ts diff --git a/Examples/JavaScript/Working With Classes/This.ts b/Examples/en/JavaScript/Working With Classes/This.ts similarity index 78% rename from Examples/JavaScript/Working With Classes/This.ts rename to Examples/en/JavaScript/Working With Classes/This.ts index 442a22d43e24..c15b5939a99d 100644 --- a/Examples/JavaScript/Working With Classes/This.ts +++ b/Examples/en/JavaScript/Working With Classes/This.ts @@ -15,8 +15,8 @@ class Safe { } } -const a = new Safe("Crown Jewels") -a.printContents() +const safe = new Safe("Crown Jewels") +safe.printContents() // If you come form an objected oriented language where the // this/self variable is easily predictable, then you may @@ -32,7 +32,7 @@ a.printContents() // object, and then call it through that - the this variable // has moved refer to the hosting object: -const customObjectCapturingThis = { contents: "http://gph.is/VxeHsW", print: a.printContents } +const customObjectCapturingThis = { contents: "http://gph.is/VxeHsW", print: safe.printContents } customObjectCapturingThis.print() // Prints "http://gph.is/VxeHsW" - not "Crown Jewels" // This is tricky, because when dealing with callback APIs - @@ -40,14 +40,14 @@ customObjectCapturingThis.print() // Prints "http://gph.is/VxeHsW" - not "Crown // directly. This can be worked around by creating a new // function at the call site. -const objectNotCapturingThis = { contents: "N/A", print: () => a.printContents() } +const objectNotCapturingThis = { contents: "N/A", print: () => safe.printContents() } objectNotCapturingThis.print() // There are a few are ways to work around this problem. One // route is to force the binding of this, to be the object // you originally intended via bind. -const customObjectCapturingThisAgain = { contents: "N/A", print: a.printContents.bind(a) } +const customObjectCapturingThisAgain = { contents: "N/A", print: safe.printContents.bind(a) } customObjectCapturingThisAgain.print() // To work around an unexpected this context, you can also @@ -72,12 +72,19 @@ class SafelyBoundSafe { // Now passing the function to another object // to run does not accidentally change this -const safeSafe = new SafelyBoundSafe("Golden Skull") -safeSafe.printContents() +const saferSafe = new SafelyBoundSafe("Golden Skull") +saferSafe.printContents() const customObjectTryingToChangeThis = { contents: "http://gph.is/XLof62", - print: safeSafe.printContents + print: saferSafe.printContents } customObjectTryingToChangeThis.print() + +// If you have a TypeScript project, you can use the compiler +// flag noImplicitThis to highlight cases where TypeScript +// cannot determine what type "this" is for a function. +// +// You can learn more about that in the handbook +// https://www.typescriptlang.org/docs/handbook/utility-types.html#thistypet diff --git a/Examples/en/TypeScript/Advanced Meta-Types/Conditional Types.ts b/Examples/en/TypeScript/Advanced Meta-Types/Conditional Types.ts new file mode 100644 index 000000000000..9eef350d6068 --- /dev/null +++ b/Examples/en/TypeScript/Advanced Meta-Types/Conditional Types.ts @@ -0,0 +1,103 @@ +// Conditionals Types provide a way to do simple logic in the +// TypeScript type system. This is definitely an advanced +// feature, and it's quite feasible that you won't need to +// use this in your normal day to day code. + +// A conditional type looks like: +// +// A extends B ? C : D +// +// Where the conditional is whether a type extends an +// expression, and if so what type should be returned. A +// type could also be deferred for + +// Let's go through some simple examples + +type Cat = { meows: true } +type Dog = { barks: true } +type Cheetah = { meow: true, fast: true } +type Wolf = { barks: true, howls: true } + +// We can create a conditional type which lets use extract +// types which only conform to something which barks. + +type ExtractDogish = A extends { barks: true } ? A : never + +// Then we can create types which ExtractDogish wraps: + +// A cat doesn't bark, so it will return never +type NeverCat = ExtractDogish +// A wolf will bark, so it returns the wolf +type Wolfish = ExtractDogish + +// This becomes useful when you want to work with a +// union of many types and reduce the number of potential +// options in a union, + +type Animals = Cat | Dog | Cheetah | Wolf + +// When you apply ExtractDogish to a union type, it is the +// same as running the conditional against each member of +// the type + +type Dogish = ExtractDogish + +// = ExtractDogish | ExtractDogish | +// ExtractDogish | ExtractDogish + +// = never | Dog | never | Wolf + +// = Dog | Wolf (see example:unknown-and-never) + +// This is call a distributive conditional type because the +// type distributes over each member of the union. + + +// Deferred Conditional Types + +// Conditional types can be used to tighten your APIs which +// can return different types depending on the inputs. + +// For example this function which could return either a +// string or number depending on the boolean passed in. + +declare function getUserID(user: {}, oldSystem: T): T extends true ? string : number + +// Then depending on how much the type-system knows about +// the boolean, you will get different return types: + +let stringReturnValue = getUserID({}, /* oldSystem */ true) +let numberReturnValue = getUserID({}, /* oldSystem */ false) +let stringOrID = getUserID({}, /* oldSystem */ Math.random() < 0.5) + +// In this case above TypeScript can know the return value +// instantly. However, you can use conditional types in functions +// where the type isn't known yet. This is called a deferred +// conditional type. + +// Same as our Dogish above, but as a function instead +declare function isCatish(x: T): T extends { meows: true } ? T : undefined; + +// In this Generic function there are no constraints on the +// generic parameter U, and so it could be any type. + +// This means using Catish would need to wait to know what +// the actual type of U is before it can be applied. + +function findOtherAnimalsOfType(animal: U) { + let maybeCat = isCatish(animal) + + // You can use assignment to short-circuit the process + // if you' have a good idea about the types during + // implementation + let b: Cat | Cheetah | undefined = maybeCat; + return maybeCat +} + +const a = findOtherAnimalsOfType({ meow: true, fast: true }) +const b = findOtherAnimalsOfType({ meows: true}) + +// TODO: This example needs work! + + +// typeof process("foo") diff --git a/Examples/TypeScript/Advanced Meta-Types/Discriminate Types.ts b/Examples/en/TypeScript/Advanced Meta-Types/Discriminate Types.ts similarity index 100% rename from Examples/TypeScript/Advanced Meta-Types/Discriminate Types.ts rename to Examples/en/TypeScript/Advanced Meta-Types/Discriminate Types.ts diff --git a/Examples/TypeScript/Language Extensions/Enums.ts b/Examples/en/TypeScript/Language Extensions/Enums.ts similarity index 100% rename from Examples/TypeScript/Language Extensions/Enums.ts rename to Examples/en/TypeScript/Language Extensions/Enums.ts diff --git a/Examples/TypeScript/Language Extensions Two/Types vs Interfaces.ts b/Examples/en/TypeScript/Language Extensions/Types vs Interfaces.ts similarity index 100% rename from Examples/TypeScript/Language Extensions Two/Types vs Interfaces.ts rename to Examples/en/TypeScript/Language Extensions/Types vs Interfaces.ts diff --git a/Examples/en/TypeScript/Language/Soundness.ts b/Examples/en/TypeScript/Language/Soundness.ts new file mode 100644 index 000000000000..4e3d12871c71 --- /dev/null +++ b/Examples/en/TypeScript/Language/Soundness.ts @@ -0,0 +1,23 @@ +// Without a background in type theory, you're unlikely +// to be familiar with the idea of a type system being "sound" + +// Soundness is the idea that the compiler can make guarantees +// about what types are available at runtime, and not just +// during compilation. + +// Building a type system for a language is a trade-off with +// three qualities: Simplicity, Usability and Soundness. + +// By aiming to support all JavaScript code, TypeScript +// varies its + +// code. While runtime safety is an important requirement, +// usability is another important one. + +// One of these usability trade-offs is in having a completely +// sound type-system vs having a type system that maps to real +// world usage of JavaScript + + + +// https://github.com/Microsoft/TypeScript/issues/9825 diff --git a/Examples/TypeScript/Primitives/Type Widening:Narrowing.ts b/Examples/en/TypeScript/Language/Type Widening:Narrowing.ts similarity index 100% rename from Examples/TypeScript/Primitives/Type Widening:Narrowing.ts rename to Examples/en/TypeScript/Language/Type Widening:Narrowing.ts diff --git a/Examples/TypeScript/Meta-Types/Indexed Types.ts b/Examples/en/TypeScript/Meta-Types/Indexed Types.ts similarity index 100% rename from Examples/TypeScript/Meta-Types/Indexed Types.ts rename to Examples/en/TypeScript/Meta-Types/Indexed Types.ts diff --git a/Examples/en/TypeScript/Meta-Types/Mapped Types.ts b/Examples/en/TypeScript/Meta-Types/Mapped Types.ts new file mode 100644 index 000000000000..03adaf6358f6 --- /dev/null +++ b/Examples/en/TypeScript/Meta-Types/Mapped Types.ts @@ -0,0 +1,57 @@ +// Mapped types are a way to creates new types based +// on another type. Effectively a transformational type. + +// Common cases for using a mapped type is dealing with +// partial subsets of an existing type. For example +// an API may return an Artist: + +interface Artist { + id: number + name: string; + bio: string; +} + +// However, if you were to send an update to the API which +// only changes a subset of the Artist then you would +// typically have to create an additional type: + +interface ArtistForEdit { + id: number + name?: string + bio?: string +} + +// It's very likely that this would get out of sync with +// the Artist above. Mapped types let you create a change +// in an existing type. + +type MyPartialType = { + // For every existing property inside the type of Type + // convert it to be a ?: version + [Property in keyof Type]?: Type[Property]; +} + +// Now we can use the mapped type instead to create +// our edit interface: +type MappedArtistForEdit = MyPartialType + +// This is close to perfect, but it does allow id to be null +// which should never happen. So, let's make one quick +// improvement by using an intersection type (see: +// example:union-and-intersection-types ) + +type MyPartialTypeForEdit = { + [Property in keyof Type]?: Type[Property]; +} & { id: number } + +// This takes the partial result of the mapped type, and +// merges it with an object which has id: number set. +// Effectively forcing id to be in the type. + +type CorrectMappedArtistForEdit = MyPartialTypeForEdit + +// This is a pretty simple example of how mapped type +// work, but covers most of the basics. If you'd like to +// dive in with more depth, check out the hand-book +// +// https://www.typescriptlang.org/docs/handbook/advanced-types.html#mapped-types diff --git a/Examples/TypeScript/Meta-Types/Nominal Typing.ts b/Examples/en/TypeScript/Meta-Types/Nominal Typing.ts similarity index 100% rename from Examples/TypeScript/Meta-Types/Nominal Typing.ts rename to Examples/en/TypeScript/Meta-Types/Nominal Typing.ts diff --git a/Examples/en/TypeScript/Primitives/Any.ts b/Examples/en/TypeScript/Primitives/Any.ts new file mode 100644 index 000000000000..765d6ca2c781 --- /dev/null +++ b/Examples/en/TypeScript/Primitives/Any.ts @@ -0,0 +1,33 @@ +// Any is the TypeScript escape clause. You can use any to +// either declare a section of your code to be dynamic and +// JavaScript like, or to work around limitations in the +// type system. + +// A good case for any is JSON parsing: + +const myObject = JSON.parse("{}") + +// Any declares to TypeScript to trust your code as being +// safe because you know more about it. Even if that is +// not strictly true. For example, this code would crash: + +myObject.x.y.z + +// Using an any gives you the ability to write code closer to +// original JavaScript with the trade off of type safety. + +// Any is considered a top type in type theory, which means +// that all other objects (except never) can be classed as +// an any - this makes it a good case for functions which +// have a very open allowance for input. + +declare function debug(value: any) + +debug("a string") +debug(23) +debug({ color: "blue" }) + +// Unknown is a sibling type to any, if any is about saying +// "I know what's best", then unknown is a way to say "I'm +// not sure what is best, so you need to tell TS the type" +// example:unknown-and-never diff --git a/Examples/en/TypeScript/Primitives/Literals.ts b/Examples/en/TypeScript/Primitives/Literals.ts new file mode 100644 index 000000000000..217c2875edc1 --- /dev/null +++ b/Examples/en/TypeScript/Primitives/Literals.ts @@ -0,0 +1,69 @@ +// TypeScript has some fun special cases for literals in +// source code. + +// In part, a lot of the support is covered in type widening +// and narrowing ( example:type-widening-narrowing ) and it's +// worth covering that first. + +// A literal is a more concrete subtype of a collective type. +// What this means is that "Hello World" is a string, but a +// string is not "Hello World" inside the type system + +const helloWorld = "Hello World" +let hiWorld = "Hi World" // this is a string because it is let + +// This function takes all strings +declare function allowsAnyString(arg: string) +allowsAnyString(helloWorld) +allowsAnyString(hiWorld) + +// This function only accepts the string literal "Hello World" +declare function allowsOnlyHello(arg: "Hello World") +allowsOnlyHello(helloWorld) +allowsOnlyHello(hiWorld) + +// This lets you declare APIs which use unions to say it +// only accepts a particular literal: + +declare function allowsFirstFiveNumbers(arg: 1 | 2 | 3 | 4 | 5) +allowsFirstFiveNumbers(1) +allowsFirstFiveNumbers(10) + +let potentiallyAnyNumber = 3 +allowsFirstFiveNumbers(potentiallyAnyNumber) + +// At first glance, this rule isn't applied to complex objects + +const myUser = { + name: "Sabrina" +} + +// See how it transforms name: "Sabrina" to name: string? +// even though it is defined as a constant. This is because +// the name can still change any time: + +myUser.name = "Cynthia" + +// Because myUser's name property can change, TypeScript +// cannot use the literal version in the type system. There +// is a feature which will allow you to do this however. + +const myUnchangingUser = { + name: "Fatma" +} as const + +// When "as const" is applied to the object, then it becomes +// a object literal which doesn't change instead of a +// mutable object which can. + +myUnchangingUser.name = "RaƮssa" + +// "as const" is a great tool for fixtured data, and places +// where you treat code as literals inline. As const also +// works with arrays + +const exampleUsers = [ + { name: "Brian" }, + { name: "Fahrooq" } +] as const + diff --git a/Examples/TypeScript/Advanced Meta-Types/Union and Intersection Types.ts b/Examples/en/TypeScript/Primitives/Union and Intersection Types.ts similarity index 100% rename from Examples/TypeScript/Advanced Meta-Types/Union and Intersection Types.ts rename to Examples/en/TypeScript/Primitives/Union and Intersection Types.ts diff --git a/Examples/TypeScript/Language Extensions/Unknown and Never.ts b/Examples/en/TypeScript/Primitives/Unknown and Never.ts similarity index 88% rename from Examples/TypeScript/Language Extensions/Unknown and Never.ts rename to Examples/en/TypeScript/Primitives/Unknown and Never.ts index c11302b5566e..a2aa5b403216 100644 --- a/Examples/TypeScript/Language Extensions/Unknown and Never.ts +++ b/Examples/en/TypeScript/Primitives/Unknown and Never.ts @@ -49,7 +49,6 @@ myUserAccount.name const neverReturns = () => { // If it throws on the first line throw new Error("Always throws, never returns") - } // If you hover on the type, you see it is a () => never @@ -68,7 +67,9 @@ const validateUser = (user: User) => { } // According to the type system, this - // codepath can never happen. + // codepath can never happen. This is because + // the two nevers match + return neverReturns() } @@ -107,3 +108,17 @@ const flowerLatinName = (flower: Flower) => { // You will get a compiler error saying that your new // flower type cannot be converted into never. + + +// Never in Unions + +// A never is something which is automatically removed from +// a type union. + +type NeverIsRemoved = string | never | number + +// If you look at the type for NeverIsRemoved, you see that +// it is string | number. This is because it should never +// happen at runtime because you cannot assign to it. + +// This feature is used a lot in example:conditional-types diff --git a/Examples/en/TypeScript/Type Primitives/Built-in Utility Types.ts b/Examples/en/TypeScript/Type Primitives/Built-in Utility Types.ts new file mode 100644 index 000000000000..0085ea43551a --- /dev/null +++ b/Examples/en/TypeScript/Type Primitives/Built-in Utility Types.ts @@ -0,0 +1,131 @@ +//// { order: 3, compiler: { strictNullChecks: true } } + +// When a particular type feels like it's useful in most +// codebases, they are added into TypeScript and become +// available for anyone which means you can consistently +// rely on their availability + +// Partial + +// Takes a type and converts all of the properties on it +// to be a optional. + +interface Sticker { + id: number + name: string + createdAt: string + updatedAt: string + submitter: undefined | string +} + +type StickerUpdateParam = Partial + + +// Readonly + +// Takes an object and makes the properties on it read-only + +type StickerFromAPI = Readonly + + +// Record] + +// Creates a type which uses the list of properties from +// KeysFrom and gives them the value of Type + +// List which keys come from: +type NavigationPages = 'home' | 'stickers' | 'about' | 'contact' + +// The shape of the data for which each of ^ is needed: +interface PageInfo { + title: string + url: string + axTitle?: string +} + +const navigationInfo: Record = { + home: { title: "Home", url: "/" }, + about: { title: "About" , url: "/about"}, + contact: { title: "Contact", url: "/contact" }, + stickers: { title: "Stickers", url: "/stickers/all" } +} + +// Pick + +// Creates a type by picking the set of properties Keys +// from Type. Essentially an allowlist for extracting type +// information from a type. + +type StickerSortPreview = Pick + + +// Omit + +// Creates a type by removing the set of properties Keys +// from Type. Essentially a blocklist for extracting type +// information from a type. + +type StickerTimeMetadata = Omit + + +// Exclude + +// Creates a type where any property in Type's properties +// which don't overlap with RemoveUnion. + +type HomeNavigationPages = Exclude + + +// Extract + +// Creates a type where any property in Type's properties +// are included if they overlap with MatchUnion. + +type DynamicPages = Extract + + +// `NonNullable` + +// Creates a type by excluding null and undefined from a set +// of properties. Useful when you have a validation check. + +type StickerLookupResult = Sticker | undefined | null +type ValidatedResult = NonNullable + + +// ReturnType + +// Extracts the return value from a Type. + +declare function getStickerByID(id: number): Promise +type StickerResponse = ReturnType + + +// InstanceType + +// Creates a type which is an instance of a class, or object +// with a constructor function. + +class StickerCollection { + stickers: Sticker[] +} + +type CollectionItem = InstanceType + + +// Required + +// Creates a type which converts all optional properties +// to be required. + +type AccessiblePageInfo = Required + + +// ThisType + +// Unlike other types, ThisType does not return a new +// type but instead manipulates the definition of this +// inside a function. You can only use ThisType when you +// have noImplicitThis turned on in your TSConfig + +// If you'd like to understand ThisType, you are diff --git a/Examples/TypeScript/Language Extensions/Nullable Types.ts b/Examples/en/TypeScript/Type Primitives/Nullable Types.ts similarity index 100% rename from Examples/TypeScript/Language Extensions/Nullable Types.ts rename to Examples/en/TypeScript/Type Primitives/Nullable Types.ts diff --git a/Examples/TypeScript/Language Extensions/Tuples.ts b/Examples/en/TypeScript/Type Primitives/Tuples.ts similarity index 100% rename from Examples/TypeScript/Language Extensions/Tuples.ts rename to Examples/en/TypeScript/Type Primitives/Tuples.ts diff --git a/Examples/scripts/generateTOC.js b/Examples/scripts/generateTOC.js index 276decfa7886..ac7970910f17 100644 --- a/Examples/scripts/generateTOC.js +++ b/Examples/scripts/generateTOC.js @@ -28,7 +28,7 @@ const getFilePaths = (folderPath) => { * @property {any} compilerSettings - name */ -const root = join(__dirname, "..") +const root = join(__dirname, "..", "en") const allJS = getFilePaths(join(root, "JavaScript")) const allTS = getFilePaths(join(root, "JavaScript"))