Skip to content

Programming languages

Синтаксис, библиотеки, фреймворки, алгоритмы, ООП, функциональное, асинхронное, многопоточное программирование. Помощь новичкам, советы экспертов, тренды и кейсы. Решайте задачи, делитесь кодом.

2 Topics 2 Posts

  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 1 Topics
    1 Posts
    JspiJ
    TypeScript continues to evolve with powerful features that enhance type safety and developer experience. One such feature introduced in TypeScript 4.9 is the satisfies operator—a versatile tool that bridges the gap between type checking and type preservation. In this article, we’ll explore what makes this operator special and how it can improve your TypeScript code. What is the satisfies Operator? The satisfies operator allows you to verify that an expression matches a particular type while preserving its most specific form. It acts as a guard that ensures type compatibility without altering the inferred type of the expression. Basic Syntax {expression} satisfies Type This syntax checks that expression conforms to Type, but maintains the expression’s original type information. The Problems It Solves 1. Preserving Literal Types Before satisfies, developers often faced a dilemma between type safety and preserving literal types: // Without satisfies const colors = { red: "#FF0000", green: "#00FF00", blue: "#0000FF" } as const; // Type: { readonly red: "#FF0000", readonly green: "#00FF00", readonly blue: "#0000FF" } // With satisfies const colors = { red: "#FF0000", green: "#00FF00", blue: "#0000FF" } satisfies Record<string, string>; // Type preserved: { red: "#FF0000", green: "#00FF00", blue: "#0000FF" } 2. Validating Partial Conformance The operator excels at verifying structural compatibility while maintaining full type information: interface User { id: number; name: string; email?: string; } const user = { id: 1, name: "John", age: 30 } satisfies User; // TypeScript knows all properties: { id: number, name: string, age: number } Practical Use Cases Configuration Validation interface AppConfig { name: string; port: number; environment: "development" | "staging" | "production"; } const config = { name: "My App", port: 3000, environment: "development" // Auto-completion works! } satisfies AppConfig; Color Palettes and Themes type ColorPalette = Record<string, string>; const colors = { primary: "#3498db", secondary: "#2ecc71", accent: "#e74c3c", // Error: Type 'number' is not assignable to type 'string' // warning: 123 satisfies string } satisfies ColorPalette; Discriminated Unions type Shape = | { kind: "circle"; radius: number } | { kind: "rectangle"; width: number; height: number }; const circle = { kind: "circle", radius: 5, } satisfies Shape; // TypeScript knows this is a circle with radius property console.log(circle.radius); // OK Comparative Analysis satisfies vs Type Annotations // Type annotation const obj1: { x: number } = { x: 1, y: 2 }; // Error: Property 'y' does not exist on type '{ x: number; }' // satisfies const obj2 = { x: 1, y: 2 } satisfies { x: number }; // OK: Checks compatibility while preserving full type satisfies vs Type Assertions (as) // Type assertion (potentially unsafe) const obj1 = { x: 1, y: 2 } as { x: number }; // OK, but loses information about 'y' // satisfies const obj2 = { x: 1, y: 2 } satisfies { x: number }; // OK: Verifies compatibility while maintaining complete type information Advanced Patterns Combining with as const const routes = { home: "/", about: "/about", contact: "/contact" } as const satisfies Record<string, string>; // Type: { readonly home: "/", readonly about: "/about", readonly contact: "/contact" } Complex Structure Validation type ResponseShape = | { status: "success"; data: unknown } | { status: "error"; message: string }; const apiResponse = { status: "success", data: { id: 1, name: "John" } } satisfies ResponseShape; // TypeScript knows the exact response structure if (apiResponse.status === "success") { console.log(apiResponse.data); // OK } Limitations and Considerations Not a type annotation replacement: Only verifies compatibility without assigning types Structural compatibility focus: Works with shapes rather than nominal types No type narrowing: Preserves the original expression type exactly Conclusion The satisfies operator represents a significant step forward in TypeScript’s type system, offering a elegant solution for situations where you need to: Verify type compatibility without losing specific type information Maintain literal types while ensuring structural validity Validate partial conformance to interfaces Enhance type safety without compromising flexibility By incorporating satisfies into your TypeScript workflow, you can write more robust, maintainable code that leverages TypeScript’s powerful type system while preserving the precise type information that makes your code more expressive and reliable. As TypeScript continues to evolve, features like satisfies demonstrate the language’s commitment to providing developers with tools that combine type safety with practical flexibility—a combination that makes TypeScript increasingly valuable for projects of any scale.
  • 1 Topics
    1 Posts
    JspiJ
    Modularity is a fundamental principle of modern development, allowing code to be organized into independent, reusable components. JavaScript’s module system evolution has led to several standards, each with its own specifics and use cases. Main JavaScript Module Systems 1. CommonJS - Server Standard Usage: Originally created for Node.js, now also used in browsers via bundlers. Syntax: // Export module.exports = { functionA, variableB }; exports.functionC = functionC; // Import const module = require('./module'); const { functionA } = require('./module'); Support: Node.js: all versions Browsers: via Webpack, Browserify, Rollup 2. AMD (Asynchronous Module Definition) Usage: Designed for browsers with asynchronous loading. Syntax: // Module definition define(['dependency'], function(dependency) { return { exportedFunction: function() { // use dependency } }; }); // Module loading require(['module'], function(module) { module.exportedFunction(); }); Support: Browsers: via RequireJS Node.js: via wrappers 3. UMD (Universal Module Definition) Usage: Cross-platform solution compatible with CommonJS, AMD and global variables. Syntax: (function(root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['exports'], factory); } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') { // CommonJS factory(exports); } else { // Global variable factory((root.myModule = {})); } }(typeof self !== 'undefined' ? self : this, function(exports) { // Module code exports.example = function() {}; })); 4. ES6 Modules - Native Standard Usage: Modern ECMAScript standard supported by all current environments. Syntax: // Export export const name = 'value'; export function functionName() {}; export default function() {}; // Import import { name, functionName } from './module'; import defaultExport from './module'; Browser Support ES6 Modules in Browsers Chrome: since version 61 (2017) Firefox: since version 60 (2018) Safari: since version 11 (2017) Edge: since version 16 (2017) Usage: <!-- Module loading --> <script type="module" src="app.js"></script> <!-- Inline module --> <script type="module"> import { functionName } from './module.js'; functionName(); </script> Legacy Browser Support For browsers without ES6 module support use: Transpilation (Babel) Module bundlers (Webpack, Rollup, Parcel) Combination of type=“module” and nomodule: <script type="module" src="app.es6.js"></script> <script nomodule src="app.legacy.js"></script> Node.js Support Module Support History Node.js 0.1.0-8.x: CommonJS only Node.js 8.5.0: experimental ES6 module support (with --experimental-modules flag) Node.js 12.0.0: improved ES6 module support Node.js 13.2.0: stable ES6 module support without flags Node.js 14.0.0+: full ES6 module support in LTS releases Using ES6 Modules in Node.js .mjs extension: // module.mjs export const value = 10; // app.mjs import { value } from './module.mjs'; “type” field in package.json: { "type": "module", "main": "app.js" } Mixed projects: .js files - CommonJS .mjs files - ES6 modules .cjs files - CommonJS (when “type”: “module”) Practical Recommendations Module System Selection New projects: use ES6 modules Libraries: support both CommonJS and ES6 (via dual export) Legacy projects: stay with CommonJS until refactoring Cross-Module System Compatibility Importing CommonJS in ES6: import { createRequire } from 'module'; const require = createRequire(import.meta.url); const commonJSModule = require('./common-js-module.cjs'); Importing ES6 in CommonJS (with dynamic import): async function loadModule() { const es6Module = await import('./es6-module.mjs'); } Build Optimization Use tree-shaking with ES6 modules Minimize circular dependencies Split code with dynamic imports Migration from CommonJS to ES6 Modules Rename files to .mjs or set “type”: “module” Replace module.exports with export Replace require() with import Update relative import paths (add extensions) Fix __dirname and __filename references Migration Example Before (CommonJS): // math.js const PI = 3.14; function sum(a, b) { return a + b; } module.exports = { PI, sum }; // app.js const { PI, sum } = require('./math'); console.log(sum(5, 10)); After (ES6 modules): // math.js export const PI = 3.14; export function sum(a, b) { return a + b; } // app.js import { PI, sum } from './math.js'; console.log(sum(5, 10)); Module Tools Bundlers and Transpilers Webpack: supports all module systems Rollup: optimized for ES6 modules Babel: transpiles ES6+ to compatible code Parcel: zero configuration, supports all formats Utilities esm: package for using ES6 modules in Node.js @babel/plugin-transform-modules-commonjs: transforms ES6 to CommonJS Conclusion JavaScript’s module ecosystem has evolved significantly, with ES6 modules becoming the universal solution for all platforms. For new projects, use ES6 modules with transpilation and bundling for backward compatibility. For existing CommonJS projects, plan gradual migration to ES6 modules using modern Node.js features and bundlers. This improves performance, enables tree-shaking, and simplifies long-term maintenance. Regardless of the chosen module system, remember the core principles of modularity: loose coupling, strong cohesion, and clear interfaces between system components.
  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 0 0
    0 Topics
    0 Posts
    No new posts.
  • 0 0
    0 Topics
    0 Posts
    No new posts.