惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V
Visual Studio Blog
F
Full Disclosure
B
Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
Lohrmann on Cybersecurity
月光博客
月光博客
I
Intezer
博客园 - 三生石上(FineUI控件)
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园_首页
P
Proofpoint News Feed
C
Check Point Blog
N
News | PayPal Newsroom
H
Heimdal Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
G
GRAHAM CLULEY
WordPress大学
WordPress大学
C
CERT Recently Published Vulnerability Notes
Y
Y Combinator Blog
Recorded Future
Recorded Future
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tailwind CSS Blog
W
WeLiveSecurity
L
LINUX DO - 热门话题
Microsoft Azure Blog
Microsoft Azure Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Schneier on Security
Schneier on Security
爱范儿
爱范儿
Martin Fowler
Martin Fowler
U
Unit 42
T
Troy Hunt's Blog
S
Securelist
V
V2EX
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
罗磊的独立博客
小众软件
小众软件
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News

oida.dev | TypeScript, Rust

TypeScript's `erasableSyntaxOnly` Flag Unsafe for work Tokio: Macros Tokio: Channels Tokio: Getting Started Network Applications on the Tokio Stack Remake, Remodel, Reduce. The `never` type and error handling in TypeScript 5 Inconvenient Truths about TypeScript Refactoring in Rust: Introducing Traits Refactoring in Rust: Abstraction with the Newtype Pattern Announcing the TypeScript Cookbook TypeScript: Iterating over objects The road to universal JavaScript 10 years of oida.dev Rust: Tiny little traits The TypeScript converging point How not to learn TypeScript Getting started with Rust Introducing Slides and Coverage TypeScript: The humble function overload TypeScript + React: Children types are broken TypeScript: In defense of any Rust: Enums to wrap multiple errors Dissecting Deno Error handling in Rust TypeScript: Unexpected intersections Upgrading Node.js dependencies after a yarn audit TypeScript: Array.includes on narrow types TypeScript + React: Typing Generic forwardRefs shared, util, core: Schroedinger's module names Learning Rust and Go TypeScript: Narrow types in catch clauses TypeScript: Low maintenance types Tidy TypeScript: Name your generics Tidy TypeScript: Avoid traditional OOP patterns Tidy TypeScript: Prefer type aliases over interfaces Tidy TypeScript: Prefer union types over enums My new book: TypeScript in 50 Lessons Go Preact! ❤️ this in JavaScript and TypeScript TypeScript and ECMAScript Modules TypeScript + React: Why I don't use React.FC TypeScript + React: Component patterns TypeScript: Augmenting global and lib.dom.d.ts Vite with Preact and TypeScript TypeScript: Union to intersection type 11ty: Generate Twitter cards automatically Are large node module dependencies an issue? TypeScript: Variadic Tuple Types Preview TypeScript: Improving Object.keys Remake, Remodel. Part 4. TypeScript + React: Typing custom hooks with tuple types TypeScript: Assertion signatures and Object.defineProperty TypeScript: Check for object properties and narrow down type Boolean in JavaScript and TypeScript void in JavaScript and TypeScript Symbols in JavaScript and TypeScript Why I use TypeScript TypeScript + React: Extending JSX Elements TypeScript: Validate mapped types and const context TypeScript: Match the exact object shape TypeScript: The constructor interface pattern Streaming your Meetup - Part 4: Directing and Streaming with OBS Streaming your Meetup - Part 3: Speaker audio Streaming your Meetup - Part 2: Speaker video Streaming your Meetup - Part 1: Basics and Projector TypeScript and React Guide: Added a new styles chapter TypeScript and React Guide: Added a new render props chapter TypeScript and React: Styles and CSS TypeScript and React TypeScript and React Guide: Added a new prop types chapter TypeScript without TypeScript -- JSDoc superpowers TypeScript: Mapped types for type maps JAMStack vs serverless web apps The Unsung Benefits of JAMStack Sites TypeScript: Ambient modules for Webpack loaders My most favourite talks in 2018 TypeScript and React Guide: Added a new context chapter TypeScript: Type predicates JSX is syntactic sugar TypeScript and React Guide: Added a new hooks chapter Getting your CfP application right FAQ on our Angular Connect Talk: Automating UI development TypeScript and Substitutability Debugging Node.js apps in TypeScript with Visual Studio Code From Medium: Deconfusing Pre- and Post-processing From Medium: PostCSS misconceptions Saving and scraping a website with Puppeteer Cutting the mustard - 2018 edition Wordpress as CMS for your JAMStack sites My most favourite podcast episodes in 2017 My most favourite talks in 2017 My most favourite books in 2017 The Best Request Is No Request, Revisited Not so hidden figures - Organizing ScriptConf My podcast journey to ScriptCast Grid layout, grid layout everywhere! #scriptconf and #devone Object streams in Node.js
TypeScript: Built-in generic types
2018-12-12 · via oida.dev | TypeScript, Rust

TypeScript comes with a ton of built in generic types that ease your development workflow. Here’s a list of all built-in generic types, with examples!

Note: This list is probably (most definitely) not complete. If you miss something and want to have it added, please reach out to me via Twitter

See more on:

  • Readonly
  • ReadonlyArray
  • ReturnType
  • Partial
  • Required
  • NonNullable
  • Pick
  • Record
  • Extract
  • Exclude
  • Omit
  • Bottom line

Readonly #

const in JavaScript is tricky, because it only means you can’t reassign any other values to this name. It allows however for changing properties of an object. The Readonly built-in type helps:

type Point = {
x: number,
y: number
};

const p: Readonly<Point> = {
x: 4,
y: 2
};

p.x = 5; // ⚡️ compile error!

ReadonlyArray #

The generic, built-in type ReadonlyArray allows us to throw errors once we use an array function that mutates the original array. See for yourself:

const values: ReadonlyArray<number> = [1, 2, 3, 4, 5];

values.push(6); // ⚡️ compile error! This mutates the array
values.filter(x => x > 4); // ✔︎ compiles! filter returns a new array

Handy if you want to keep an immutable array!

ReturnType #

This built-in type gets you the return type of any function.

type Point = {
x: number,
y: number
}

function generateSquare(bottomLeft: Point, topRight: Point) {
return {
bottomLeft,
bottomRight: {
x: topRight.x,
y: bottomLeft.y,
},
topLeft: {
x: bottomLeft.x,
y: topRight.y
},
topRight
}
}

type Square = ReturnType<typeof generateSquare>;
// here's the magic! I can use this return type now everywhere
// in my code

function areaOfSquare(square: Square): number {
//do something
return result;
}

You can also access functions inside classes:

class Square {
generate(bottomLeft, topRight) {
return {
bottomLeft,
bottomRight: {
x: topRight.x,
y: bottomLeft.y,
},
topLeft: {
x: bottomLeft.x,
y: topRight.y
},
topRight
}
}
}

type TSquare = ReturnType<Square['generate']>;
declare let result: TSquare;

Partial #

Partial<T> is a beauty. It takes all properties from one type, and makes them optional. What is it good for? Think about having a set of default options, and you want to override just parts and pieces from them. Partial<T> helps you getting autocomplete and type-checking for that case:

const defaultOptions = {
directory: '.',
incremental: true,
filePattern: '**/*',
}

function start(options: Partial<typeof defaultOptions>) {
const allOptions = Object.assign({}, defaultOptions, options);
console.log(allOptions);
}

start({
incremental: false, // Awesome! Typechecks!
});

start({
flatten: true // ⚡️ Error! This property has nothing to do with our options
});

Required #

Required<T> is the opposite to Partial<T>. Where Partial<T> makes every property optional, required makes ever property necessary.

type Container = {
width: number,
height: number,
children?: Container[]
}

function getChildrenArea(parent: Required<Container>) {
let sum = 0;
for (let child of parent.children) {
sum = sum + (child.width * child.height)
}
return sum;
}

const mainContainer: Container = {
width: 200,
height: 100
}

getChildrenArea(mainContainer); // ⚡️ Error: Needs children

NonNullable #

NonNullable<T> helps you to ensure you don’t pass null or undefined to your functions. This complements the strictNullChecks compiler flag, so make sure you activate it.

function print<T>(x: NonNullable<T>) {
console.log(x.toString());
}

print('Hello');
print(2);
print(null); // ⚡️ Error
print(undefined); // ⚡️ Error

Pick #

With Pick<T, K extends keyof T> you can create a new type from an existing object, by only using a selected list of properties. Lodash’s eponymous pick function is a good example of its usage:

/**
* The pick function is generic as well. It has two generic types:
* - T ... the type of the object we want to pick props from
* - K ... a subset of all keys in T
*
* Our method signature takes an object of type T, the other parameters
* are collected in an array of type K.
*
* The return type is a subset of keys of T.
*/

declare function pick<T, K extends keyof T>(obj: T, ...propsToPick: K[]): Pick<T, K>;

const point3D = {
x: 2,
y: 0,
z: 4
}

const point2D = pick(point3D, 'x', 'y'); // returns a type { x: number, y: number }

This one is especially useful when used with other generic types, e.g. Exclude.

Record #

Record<K, T> is funny. With it you can say that *every key K should be of type T. With it you can do things like

type Person = Record<'firstName' | 'lastName', string>

which is the same as { firstName: string, lastName: string }. Or, something like

type MetaInfo = {
title: string,
url: string
}

type Episodes = Record<string, MetaInfo>

Which allows an object with any key possible, but values of type MetaInfo. This is very much alike to { [k: string]: MetaInfo }.

So far, so good. But why have this generic Record type if we can achieve similar, if not the same results with other methods? Record helps when you deal with other generic types. Let’s look at that example: We can create a function that transforms all values of an object to a string representation:

// The implementation is somewhere else. It converts all values to strings.
declare function allToString<T>(obj: T): Record<keyof T, string>;

const person = {
firstName: 'Stefan',
lastName: 'Baumgartner',
age: Number.MAX_VALUE
}

// all properites in strPerson are now strings
const strPerson = allToString(person);

Check it out here;

Extract<T, K> extracts all types from T that are assignable to K. Let’s say you have two different types of shape. Circles and rectangles. They look something like that:

const rect = {
width: 200,
height: 100,
area() {
return this.width * this.height;
},
perimeter() {
return this.width * 2 + this.height * 2;
}
}

const circle = {
r: 50,
area() {
return this.r * this.r * Math.PI;
},
perimeter() {
return 2 * this.r * Math.PI;
}
}

Their types are

type Rect = typeof rect;
type Circle = typeof circle;

They have something in common: They both have the same methods for area and perimeter. These objects might change over time. We still want to make sure that we only access methods that are available in both of them. With Extract, we can get the keys of those functions:

// extracts: 'area' | 'perimeter'
type ShapeFunctionProps = Extract<keyof Rect, keyof Circle>

To create a type that has access to all those functions again, we can use the Record type from earlier on:

type ShapeFunctions = Record<ShapeFunctionProps, () => number>

Now we have this extra type safety in functions that may apply to all of those objects:

declare function extensiveMath<T extends ShapeFunctions>(obj: T)

extensiveMath(rect); // ✅ compiles
extensiveMath(circle); // ✅ compiles

Exclude #

Exclude<T, K> excludes all types from T that are assignable to K. It’s like the opposite of Extract. Let’s take the example from earlier:

type Rect = typeof rect;
type Circle = typeof circle;

// only has 'width' | 'height';
type RectOnlyProperties = Exclude<keyof Rect, keyof Circle>;

// An object of type { width: number, height: number }
type RectOnly = Pick<Rect, RectOnlyProperties>;

declare function area<T extends RectOnly>(obj: T)

area({
width: 100,
height: 100
}) // ✅ compiles;

Omit #

Since version 3.5, TypeScript includes the Omit<T, K> helper type. Omit<T, K> is a shortcut for Pick<T, Exclude<keyof T, K>>, but since it was used so often, the team decided to add it:

type Person = {
name: string;
age: number;
location: string;
};

type Cosmopolitan = Omit<Person, 'location'>;

// equivalent to
type Cosmopolitan = {
name: string;
age: number;
};

Bottom line #

That’s a couple of generic built-in types that might be useful for different cases. I think the combination of all those generic types is super helpful if you want to strengthen your library or application without interfering too much. Especially when you generate type definitions for methods that allow different parameter types (as it happens often in JavaScript), they might be much more useful than defining every possible type outcome on its own.

Again, I’m sure I missed a ton. So if you have any generic built-in type that you want to have convered here, let me know.

Update: My buddy Martin Hochel has a couple of mapped types that build on top of those. They are pretty good, so check them out

Related Articles