satisfies operator
This operator seems weird to me, it is different than as const, what it does are:
- It strictly validates that a value matches a specific type.
- But, doesn't cause the value to be cast to that type.
Because it preserves the specific type, your autocomplete still works perfectly. When you type obj., your editor knows what properties exist and instantly gives you the dropdown list.
type Config = Record<string, string | number>;
const configDeclare: Config = { host: 'localhost', port: 8080 };
const configAssert = { host: 'localhost', port: 8080 } as Config;
const configConst = { host: 'localhost', port: 8080 } as const;
const configSatisfies = { host: 'localhost', port: 8080 } satisfies Config;
// Property 'toFixed' does not exist on type 'string | number'
configDeclare.port.toFixed();
configAssert.port.toFixed();
// Worked: TS: Bro, I know this type more than u.
// Autocomplete works
configSatisfies.port.toFixed();
configConst.port.toFixed();console.log(configDeclare.fake);
console.log(configAssert.fake);
// TS slap u, because u wrong.
//Property 'fake' does not exist
// on type '{ host: string; port: number; }'
console.log(configConst.fake);
console.log(configSatisfies.fake);Here is how I use satisfies in my own code:
type Example = 'foo' | 'bar';
function f(ex: Example) {
switch (ex) {
case 'foo':
// do stuff
break;
default:
// It forces me must handle 'bar' case
// Type "bar" does not satisfy the expected type 'never'.
ex satisfies never;
}
}type RouteConfig = Record<string, { url: string; protected: boolean }>;
const routes = {
home: { url: '/', protected: false },
blog: { url: '/blog', protected: true },
} as const satisfies RouteConfig;
type Routes = typeof routes;
type RoutesUrl = Routes[keyof Routes]['url']; // = '/' | '/blog'using keyword
It is Python's with statement. It allows you to define a block-scoped variable that automatically cleans up when GC touch it, even if an error is thrown.
const connection = getDatabase();
try {
// do stuff with connection
} finally {
connection.close();
}Become:
class Database {
constructor() {
this.connection = getDatabase();
}
[Symbol.dispose]() {
this.connection.close();
}
query(sql: string) {
console.log(sql);
}
}
function executeReport() {
using db = new Database();
db.query('SELECT * FROM anywhere');
}Or:
function useDatabase() {
const connection = getDatabase();
return {
connection,
[Symbol.dispose]() {
connection.close();
},
};
}
function executeReport() {
using db = useDatabase();
db.query('SELECT * FROM anywhere');
}