Örnek
Şöyle yaparız
<body><header><img src="/static/logo.png" alt="Logo"><nav><a href="/">Main page</a></nav></header><main><article><h1>Title</h1><p>Content</p></article></main><footer></footer></body>
<body><header><img src="/static/logo.png" alt="Logo"><nav><a href="/">Main page</a></nav></header><main><article><h1>Title</h1><p>Content</p></article></main><footer></footer></body>
<embed id="plugin" type="application/x-google-chrome-pdf" src="..."
...
>null Guardtypeof Guardinstanceof Guardin GuardDiscriminated Union GuardsUser-Defined Guards
const element: HTMLElement | null = document.getElementById('target');element.innerText = 'Hello'; // Compiler error - null in unionif (element !== null) {element.innerText = 'Hello'; // null removed from union}
element?.innerText = 'Hello';
// Note that the type of 'primitive' in each branch is differentswitch (typeof primitive) { case "number": return primitive.toFixed(2); case "string": return primitive.toUpperCase(); case "boolean": return !primitive; default: throw new Error("Unexpected type") }
Remember that typeof can only tell us if a type is string, number, boolean, symbol, function, bigint, undefined. Everything else will return "object".
function setupInput(input: HTMLInputElement | HTMLTextAreaElement) {
input.value = ''; // Valid since value is common to both types
if (input instanceof HTMLTextAreaElement) {
// These properties are only valid for HTMLTextAreaElement
input.rows = 25;
input.cols = 80;
input.wrap = 'hard';
} else {
// These properties are only valid for HTMLInputElement
input.width = 400;
input.height = 50;
}
}function setupInput(input: HTMLInputElement | HTMLTextAreaElement) {
if ('rows' in input) {
// These properties are only valid for HTMLTextAreaElement
input.rows = 25;
input.cols = 80;
input.wrap = 'hard';
} else {
// These properties are only valid for HTMLInputElement
input.width = 400;
input.height = 50;
}
}The in operator allows us to test an object for the existence of a member. In the code below, only HTMLTextAreaElement has a rows property so by testing for its existence the compiler determines the type of the input variable on each branch and narrows the type.Note, in can only be used if ALL members of the union are object types (not primitives).
in Guard kullanıyorsak return type'a dikkat etmek gerekir. Şöyle yaparızfunction isTextArea(input: HTMLInputElement | HTMLTextAreaElement):
input is HTMLTextAreaElement {
return 'rows' in input;
}
if (isTextArea(input)) {
// input has type HTMLTextAreaElement
input.rows = 25; // Valid
}
Eğer şöyle yapsaydık derleme hatası alırdık. Çünkü boolean dönünce "type narrowing" yapılmıyor.function isTextArea(input: HTMLInputElement | HTMLTextAreaElement): boolean {
return 'rows' in input;
}
if (isTextArea(input)) {
// input still has union type
input.rows = 25; // Compiler error
}Ayrıca TypeScipt 4.4 ile "type narrowing" şöyle de oluyor. Buna Control Flow Analysis information (CFA) deniliyor.const isTextArea = 'rows' in input;
if (isTextArea) {
// Narrowing has taken place
input.rows = 25;
}ÖrnekElimizde şöyle bir kod olsun.interface A {
text: string;
}
interface B {
type: string;
}
type C = A|B;function isB(c: C): c is B {
if ('type' in c) {
return typeof c.type === 'string';
}
return false;
}Elimizde bir array olsun.const arr: Array<C> = [....]Şöyle yaparız.const output = arr.find(isB);ÖrnekType Unions allow us to define a new type which represents any one of a set of possible types.
Kullanmak için şöyle yaparız.type Primitive =| string| number| boolean;let x: Primitive;
x = 'Hello'; x = 123; x = false; x = new Date(); // Compiler ErrorDeğişkenin tipini anlamak için şöyle yaparız.
if (typeof x === 'number') {
console.log(x.toFixed(2)); // 'x' can safely use 'number' operations
}It’s possible in TypeScript to derive new types from existing types using type unions, type intersections, mapped types, and conditional types.
ReadOnlyinterface Employee {name: stringage: number;dob: Date;}// Type Intersectiontype EmployeeWithId = Employee & { id: string };// This type will be equivalent to// {// id: string;// name: string// age: number;// dob: Date;// }// Readonly uses Mapped Typestype ReadonlyEmployee = Readonly<Employee>;// This type will be equivalent to// {// readonly name: string// readonly age: number;// readonly dob: Date;// }// A Mapped Type with a Conditional Type allows for interesting transformationstype DateToString<T> = {[P in keyof T]: T[P] extends Date ? string : T[P];};type EmployeeJson = DateToString<Employee>// This type will be equivalent to// {// name: string// age: number;// dob: string; // Date has changed to string// }
interface Employee {name: stringage: number;dob: Date;}// Readonly uses Mapped Typestype ReadonlyEmployee = Readonly<Employee>;// This type will be equivalent to// {// readonly name: string// readonly age: number;// readonly dob: Date;// }
interface Employee {name: stringage: number;dob: Date;}// A Mapped Type with a Conditional Type allows for interesting transformationstype DateToString<T> = {[P in keyof T]: T[P] extends Date ? string : T[P];};type EmployeeJson = DateToString<Employee>// This type will be equivalent to// {// name: string// age: number;// dob: string; // Date has changed to string// }
Steps To Use the Throttler1. Open DevTools (Ctrl + Shift + I)2. Switch to the Network Tab.3. By default, the throttler is set to ‘No Throttle’.4. From the dropdown menu, you can select the type of network to simulate.5. Long Press the reload icon while the DevTools panel is open.6. Select ‘Empty Cache and Hard Reload’ from the advanced reload options. It is important to empty cache to examine the page as a first time visitor.
interface Cat {name: string;age: number;ownerName?: string; // not every cat has an owner}const mrWhitePaws: Cat = {name: "Mr. White Paws",age: 7,ownerName: "Jane", // domestic cat, lucky guy};const wildLynx: Cat = {name: "Lynx lynx",age: 6,// this wild cat lives a free life!};
element?.innerText = 'Hello';
The optional chaining allows to safely “navigate” through possibly absent values (without throwing an error), while the nullish coalescing operator, or the ??, enables providing a failover (default) value in case of stumbling upon a null (think of it as a good, old || operator, but for null or undefined values only, instead of all “falsy” ones). Again, keep in mind, that this is an example of a feature eventually available in pure JavaScript, too.
// optional chaining:// The value will be undefined. Without `?.`, this would error with
// "Uncaught TypeError: Cannot read property 'length'const nameLength: string | undefined = wildLynx?.name?.length; of undefined".// nullish coalescing:const nope = null;const calculation = (nope ?? 0) + 42; // The value will be 0 + 42, ergo 42.