function printName(obj: { first: string; last?: string }) { // ... } // Both OK printName({ first: "Bob" }); printName({ first: "Alice", last: "Alisson" });
Union Types
Defining a Union Type
1 2 3 4 5 6 7
function printId(id: number | string) { //use | to separate console.log("Your ID is: " + id); } // OK printId(101); // OK printId("202");
if you have the union string | number, you can’t use methods that are only available on string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
function printId(id: number | string) { console.log(id.toUpperCase()); Property 'toUpperCase' does not exist on type'string | number'. Property 'toUpperCase' does not exist on type'number'. } // solution of upstairs function printId(id: number | string) { if (typeof id === "string") { // use typeof that Typescript knows that only a string value // In this branch, id is of type'string' console.log(id.toUpperCase()); } else { // Here, id is of type'number' console.log(id); } }
Type Aliases
use a type to give a name to any type at all
1 2 3 4 5 6 7 8 9 10 11 12
type Point = { x: number; y: number; }; // Exactly the same as the earlier example function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 100, y: 100 });
Interfaces
An interface declaration is another way to name an object type:
1 2 3 4 5 6 7 8 9 10 11
interface Point { x: number; y: number; } function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 100, y: 100 });
const src = 'const a = "Hello World"'; window.ts.transpileModule(src, {});
type Window = { // A Type cannot be changed after being created title: string; }
type Window = { ts: TypeScriptAPI; }
// Error: Duplicate identifier 'Window'.
null and undefined
strictNullChecks on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// handle method function doSomething(x: string | null) { if (x === null) { // do nothing } else { console.log("Hello, " + x.toUpperCase()); } }
// use ! after any expression function liveDangerously(x?: number | null) { // No error console.log(x!.toFixed()); }
More on Function
Function Type Expressions
Typeof Function is fn
1 2 3 4
type GreetFunction = (a: string) => void; function greeter(fn: GreetFunction) { // ... }
Generic Functions
1 2 3 4 5 6 7 8 9 10
function firstElement<Type>(arr: Type[]): Type | undefined { return arr[0]; // the Type can be meant every typereturn }
// s is of type'string' const s = firstElement(["a", "b", "c"]); // n is of type'number' const n = firstElement([1, 2, 3]); // u is of type undefined const u = firstElement([]);
Inference Function - The type were inferred - chosen automatically by Typescript
1 2 3 4 5 6 7
function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] { return arr.map(func); } // Parameter 'n' is of type'string' // 'parsed' is of type'number[]' const parsed = map(["1", "2", "3"], (n) => parseInt(n));
Specifying Type Arguments
1 2 3 4 5 6 7 8
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] { return arr1.concat(arr2); }
const arr = combine([1, 2, 3], ["hello"]); // mismatched arrays Type 'string' is not assignable to type'number'.
const arr = combine<string | number>([1, 2, 3], ["hello"]); // use specify Type
Optional Parameters
1 2 3 4 5 6 7 8 9 10 11 12 13
// method one function f(x?: number) { //marking the parameters as optional with ? // ... } f(); // OK f(10); // OK
function f(x = 10) { // param is specified as type <number | undefined>,provide a default value // ... }
// method two Partial<ListApiOption<unknown, unknown>> // use Partial before type call
OtherTypes to Know About
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 1. void // The inferred returntype is void functionnoop() { return; }
// 2. unknown function f1(a: any) { a.b(); // OK } function f2(a: unknown) { // similar to the any type,but not legal to do anything a.b(); 'a' is of type'unknown'. }
// 3. never function fail(msg: string): never { // some functions never return a value throw new Error(msg); }
Parameter Destructuring
1 2 3 4
type ABC = { a: number; b: number; c: number }; functionsum({ a, b, c }: ABC) { // unpack objects provided as an argument console.log(a + b + c); }
interface SomeType { readonly prop: string; //readonly can't be written to during type-checking } function doSomething(obj: SomeType) { // We can read from 'obj.prop'. console.log(`prop has the value '${obj.prop}'.`); // But we can't re-assign it. obj.prop = "hello"; Cannot assign to 'prop' because it is a read-only property. }
interface ReadonlyPerson { readonly name: string; readonly age: number; } let writablePerson: Person = { name: "Person McPersonface", age: 42, }; // works let readonlyPerson: ReadonlyPerson = writablePerson; console.log(readonlyPerson.age); // prints '42' writablePerson.age++; console.log(readonlyPerson.age); // prints '43'
interface Array<Type> { // Array is a generic type /** * Gets or sets the length of the array. */ length: number; /** * Removes the last element from an array and returns it. */ pop(): Type | undefined; /** * Appends new elements to an array, and returns the new length of the array. */ push(...items: Type[]): number; // ... }
function doSomething(pair: [string, number]) { const a = pair[0]; const a: string const b = pair[1]; const b: number // ... } doSomething(["hello", 42]);
// index shouldn't past the number of elements function doSomething(pair: [string, number]) { // ... const c = pair[2]; Tuple type '[string, number]' of length '2' has no element at index '2'. } // we can destructure tuples function doSomething(stringHash: [string, number]) { const [inputString, hash] = stringHash; console.log(inputString); const inputString: string console.log(hash); const hash: number }
Utility Types
Partial
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
interface Todo { title: string; description: string; } function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) { // use Partial and bracket <> inside Type return { ...todo, ...fieldsToUpdate }; } const todo1 = { title: "organize desk", description: "clear clutter", }; const todo2 = updateTodo(todo1, { description: "throw out trash", });