Skip to content

Commit

Permalink
More work on setting up the new website
Browse files Browse the repository at this point in the history
  • Loading branch information
orta committed Oct 6, 2019
1 parent f466b32 commit 66f17ad
Show file tree
Hide file tree
Showing 183 changed files with 34,462 additions and 28 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": {
"start": "yarn workspace typescriptlang-org start",
"build": "yarn workspace typescriptlang-org build",
"test": "yarn jest",
"playground": "concurrently -p \"[{name}]\" -n \"TS,WEB\" -c \"bgBlue.bold,bgMagenta.bold\" \"yarn workspace playground start\" \"yarn workspace playground-sandbox start\"",
"deploy:dev": "yarn build && az storage blob upload-batch -s 'packages/typescriptlang-org/public' -d \\$web --account-name playgroundstatichosting --subscription 'TypeScript – Internal Services'"
},
Expand Down
15 changes: 15 additions & 0 deletions packages/examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# TypeScript Example Code

The English examples can be found in [`en/`](en/).

# Deployment

There is a table of contents JSON file which contains
all the useful metadata about the hierarchy and sort
order for the docs.

It's likely that we'll need to create this per translation
in the future, but for now the table of contents will
default to english.

The script is in [`scripts/generateTOC.js`](scripts/generateTOC.js).
38 changes: 38 additions & 0 deletions packages/examples/en/3-7/Fixits/Big number literals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// { compiler: { ts: "3.7-Beta", target: 99 }, order: 1 }

// Did you know there is a limit to how big of a number you
// can represent in JavaScript when writing ?

const maxHighValue = 9007199254740991;
const maxLowValue = -9007199254740991;

// If you go one over/below these numbers
// then you start to get into dangerous territory

const oneOverMax = 9007199254740992;
const oneBelowMin = -9007199254740992;

// The solution for handling numbers of this size
// is to convert these numbers to BigInts instead
// of a number

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

// TypeScript will now offer a fixit for number
// literals which are above 2^52 (positive / negative)
// which adds the suffix "n" which informs JavaScript
// that the type should be BigNum

// Number literals
9007199254740993;
-9007199254740993;
9007199254740994;
-9007199254740994;

// Hex numbers
0x19999999999999;
-0x19999999999999;
0x20000000000000;
-0x20000000000000;
0x20000000000001;
-0x20000000000001;
12 changes: 12 additions & 0 deletions packages/examples/en/3-7/Fixits/Const to let.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//// { compiler: { ts: "3.7-Beta" }, order: 1 }

// New to 3.7 is the ability to quickly convert
// a const variable to a let when the value
// has been re-assigned.

// You can try this by highlighting the below error
// and choosing to run the quick-fix.

const displayName = "Andrew"

displayName = "Andrea"
38 changes: 38 additions & 0 deletions packages/examples/en/3-7/Fixits/Infer From Usage Changes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//// { compiler: { ts: "3.7-Beta", noImplicitAny: false }, order: 2 }

// With 3.7 TypeScript's existing 'infer from usage'
// code fix became smarter. It will now use a list of
// known important types (string, number, array, Promise)
// and infer whether the usage of a type matches the api
// of these objects.

// For the next few examples, select the parameters of
// the functions, click the light bulb and choose
// "Infer Parameter types..."

// Infer a number array:

function pushNumber(arr) {
arr.push(12)
}

// Infer a promise

function awaitPromise(promise) {
promise
.then(value => console.log(value))
}

// Infer the function, and it's return type

function inferAny(app) {
const result = app.use('hi')
return result
}

// Infer a string array because a string
// was added to it

function insertString(names) {
names[1] = "hello"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//// { compiler: { ts: "3.7-Beta" }, order: 3 }

// TypeScript's error messages can sometimes be a tad verbose...
// With 3.7, we've taken a few cases which could be particularly
// egregious.


// Nested Properties

let a = { b: { c: { d: { e: "string" } } } };
let b = { b: { c: { d: { e: 12 } } } };

a = b;

// Before, it was 2 lines of code per nested property, which
// quickly meant people learned to read error messages by
// reading the first and then last line of an error message.

// Now they're inline. :tada:

// Previously in 3.6:
//
// Type '{ b: { c: { d: { e: number; }; }; }; }' is not assignable to type '{ b: { c: { d: { e: string; }; }; }; }'.
// Types of property 'b' are incompatible.
// Type '{ c: { d: { e: number; }; }; }' is not assignable to type '{ c: { d: { e: string; }; }; }'.
// Types of property 'c' are incompatible.
// Type '{ d: { e: number; }; }' is not assignable to type '{ d: { e: string; }; }'.
// Types of property 'd' are incompatible.
// Type '{ e: number; }' is not assignable to type '{ e: string; }'.
// Types of property 'e' are incompatible.
// Type 'number' is not assignable to type 'string'


// This can handle working through different types of objects,
// to still give a useful and concise error message.

class ExampleClass {
state = "ok"
}

class OtherClass {
state = 12;
}

let x = { a: { b: { c: { d: { e: { f: ExampleClass } } } } } };
let y = { a: { b: { c: { d: { e: { f: OtherClass } } } } } };
x = y;

// Previously in 3.6:
//
// Type '{ a: { b: { c: { d: { e: { f: typeof OtherClass; }; }; }; }; }; }' is not assignable to type '{ a: { b: { c: { d: { e: { f: typeof ExampleClass; }; }; }; }; }; }'.
// Types of property 'a' are incompatible.
// Type '{ b: { c: { d: { e: { f: typeof OtherClass; }; }; }; }; }' is not assignable to type '{ b: { c: { d: { e: { f: typeof ExampleClass; }; }; }; }; }'.
// Types of property 'b' are incompatible.
// Type '{ c: { d: { e: { f: typeof OtherClass; }; }; }; }' is not assignable to type '{ c: { d: { e: { f: typeof ExampleClass; }; }; }; }'.
// Types of property 'c' are incompatible.
// Type '{ d: { e: { f: typeof OtherClass; }; }; }' is not assignable to type '{ d: { e: { f: typeof ExampleClass; }; }; }'.
// Types of property 'd' are incompatible.
// Type '{ e: { f: typeof OtherClass; }; }' is not assignable to type '{ e: { f: typeof ExampleClass; }; }'.
// Types of property 'e' are incompatible.
// Type '{ f: typeof OtherClass; }' is not assignable to type '{ f: typeof ExampleClass; }'.
// Types of property 'f' are incompatible.
// Type 'typeof OtherClass' is not assignable to type 'typeof ExampleClass'.
// Type 'OtherClass' is not assignable to type 'ExampleClass'.
// Types of property 'state' are incompatible.
// Type 'number' is not assignable to type 'string'
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//// { compiler: { ts: "3.7-Beta" }, order: 2 }

// The nullish coalescing operator is an alternative to ||
// which returns the right-side expression if the left-side
// is null or undefined.

// In contrast, || uses falsy checks, meaning an empty
// string or the number 0 would be considered false.

// A good example for this feature is dealing with partial
// objects which have defaults a key isn't passed in.

interface AppConfiguration {
// Default: "(no name)"; empty string IS valid
name: string;

// Default: -1; 0 is valid
items: number;

// Default: true
active: boolean;
}

function updateApp(config: Partial<AppConfiguration>) {
// With null-coalescing operator
config.name = config.name ?? "(no name)";
config.items = config.items ?? -1;
config.active = config.active ?? true;

// Current solution
config.name = typeof config.name === "string" ? config.name : "(no name)";
config.items = typeof config.items === "number" ? config.items : -1;
config.active = typeof config.active === "boolean" ? config.active : true;

// Using || operator which could give bad data
config.name = config.name || "(no name)"; // does not allow for "" input
config.items = config.items || -1; // does not allow for 0 input
config.active = config.active || true; // really bad, always true
}

// You can read more about nullish coalescing in the 3.7 blog post:
// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
69 changes: 69 additions & 0 deletions packages/examples/en/3-7/Syntax and Messaging/Optional Chaining.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//// { compiler: { ts: "3.7-Beta" }, order: 1 }

// Optional chaining reached TC39 Stage 3 consensus during
// 3.7's development. Optional Chaining allows you to write
// code which can immediately stop running expressions when
// it hits a null or undefined.

// Property Access

// Lets imagine we have an album where the artist, and the
// artists bio might not be present in the data. For example
// a compilation may not have a single artist.

type AlbumAPIResponse = {
title: string
artist?: {
name: string
bio?: string
previousAlbums?: string[]
}
};

declare const album: AlbumAPIResponse;

// With optional chaining, you can write
// code like this:

const artistBio = album?.artist?.bio;

// Instead of:

const maybeArtistBio = album.artist && album.artist.bio;

// In this case ?. acts differently than the &&s since &&
// will act different on "falsy" values (e.g. ab empty string,
// 0, NaN, and, well, false).

// Optional chaining will only take use null or undefined as
// a signal to stop and return an undefined.

// Optional Element Access

// Property access is via the . operator, the optional chaining
// also works with the [] operators when accessing elements.

const maybeArtistBioElement = album?.["artist"]?.["bio"];

const maybeFirstPreviousAlbum = album?.artist?.previousAlbums?.[0];

// Optional Calls

// When dealing with functions which may or may not exist at
// runtime, optional chaining supports only calling a function
// if it exists. This can replace code where you would traditionally
// write something like: if (func) func()

// For example here's an optional call to the callback from
// an API request:

const callUpdateMetadata = (metadata: any) => Promise.resolve(metadata); // Fake API call

const updateAlbumMetadata = async (metadata: any, callback?: () => void) => {
await callUpdateMetadata(metadata);

callback?.();
};

// You can read more about optional chaining in the 3.7 blog post:
// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//// { compiler: { ts: "3.7-Beta" }, order: 1 }

// Given JavaScripts flexibility, it can be a good idea to add
// runtime checks to your code to validate your assumptions.

// These are typically called assertions (or invariants) and
// they are small functions which raise errors early when
// your variables doesn't match up to what you expect.

// Node comes with a function for doing this out of the box,
// it's called assert and it's available without an import.

// We're going to define our own though, this declares a
// function which asserts that the expression called
// value is true:
declare function assert(value: unknown): asserts value;

// Now we're use it to validate the type of an enum
declare const maybeStringOrNumber: string | number
assert(typeof maybeStringOrNumber === "string")

// With TypeScript 3.7, the code flow analysis can use these
// types of functions to figure out what the code is. So,
// when you hover over the variable below - you can see that
// it has been narrowed from a string or number to
// just a string.

maybeStringOrNumber

// You can use assertion functions to make guarantees of
// your types throughout your inferred code, for example
// TypeScript knows that this function will return a
// number without the need to add types to the parameter
// via the above assert declaration

function multiply(x: any, y: any) {
assert(typeof x === "number");
assert(typeof y === "number");

return x * y;
}

// Assertion functions are siblings to Type Guards
// example:type-guards except they affect the control flow
// when it continues through the function.

// For example, we can use assertion functions to narrow
// an enum down over time:

const oneOfFirstFiveNumbers = 1 | 2 | 3 | 4 | 5

declare function isOdd(param: unknown): asserts param is 1 | 3 | 5
declare function isBelowFour(param: unknown): asserts param is 1 | 2 | 3 | 4

// This should cut down the enum to 1 | 3 | 5

isOdd(oneOfFirstFiveNumbers)
oneOfFirstFiveNumbers

// This will then cut the enum's possible states to: 1 | 3

isBelowFour(oneOfFirstFiveNumbers)
oneOfFirstFiveNumbers

// This is a primer on some of the features of assertion functions
// in TypeScript 3.7 - you can find out more by reading the
// beta release notes:

// https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
Loading

0 comments on commit 66f17ad

Please sign in to comment.