https://www.w3schools.com/typescript/typescript_getstarted.php For DIRECT *.ts execution there are ts-node which is a Node module; and deno which has better performance and security, but isn't Node-compatible. Consequently I'm sticking with ts-node for now. Start with https://typescript-eslint.io/getting-started for initializing a project for TypeScript + typescript-eslint COMMON INITIAL SETUP npm init -y # or copy in package.json. adjust package.json as usual. type:module not needed npm i typescript # this adds 'npm ls' entry: ?-- typescript@VER npx tsc --init # OR copy in a tsconfig.json file Edit tsconfig.json and change target to "es2022" enable the noImplicitAny line enable the strictNullChecks line AWESOME requires '| null' and/or '| undefined' for all type specs that allow null or undefined values! Also enables ?? operator which is like Groovy ?; var ?? subst-va-if-null-or-undefed !. means ignore-possibility-of-null-or-undefined??? enable the noImplicitOverride line add up top: "include": ["src"], enable "outDir" compilerOptions setting and set value to "./build" or "./dist", Remember to add this directory to .gitinore BUT NOT .npmignore! An article says 'add dependencies and your own types to "paths"'. An article says 'add "declaration": true so you have *.d.ts files generated' Article says 'add "types": "dist/hello.d.ts" in package.json' Article says 'add "build": "tsc" to package.json (watch out for redundant files, see below)' MANUAL BUILD METHOD: Need this if will ever use this package from elsewhere, because you need to populate build or dist to publish. mkdir src Add source files src/*.ts Build continually with: npx tsc # despite misleading "error"s, used modules need not be available GOTCHA! DO NOT specify source files to 'npx tsx'. Causes all sort of problems because then tsconfig.json is not loaded. [If you do this you must add switch '--lib es2022' and must switch your 'import x from "y"' statements to 'import * as x from "y"' execute compiled JS with: node build/something.js # must have in package.json: "type": "module" DIRECT .ts EXECUTION METHOD (via ts-node, see above re. deno). npm i -D ts-node # adds to 'npm ls' an entry: ?-- ts-node@VER 'npm i -D @types/node' ONLY NEEDED if you need to run tsc; ts-node has access to build-in modules! node_modules/.bin/ts-node x.ts # "ts-node" is smart enough to execute regular *.js files too Add interpreter line to top-level *.js files: #!/usr/bin/env node_modules/.bin/ts-node OR #!/usr/bin/env ts-node Depending only on whether ts-node is in your PATH (You can add .../node_modules/.bin to PATH). If interpreter lines added, make *.js and *.ts (other than *.d.ts) files executable. Need to support non-TS packages: If the regular package has typing then you just install it as usual with: npm [-D] name If not... ONE TIME, to look up (non-OOTB) modules in @type registry: npm i -g typings # as root If node can find them, at least for OOTB modules everything works, but the npx compilation step displays errors as if it failed. The generated *.js can be executed still! (Perhaps due to skipLibCheck?) !!! This unnecessary for ts-node executions! ts-node apparently adds default modules to env. npm i -D @types/node # pulls in all built-ins. Adds 'npm ls' entry: ?-- @types/node@VER For this @types/x method, DO NOT need to explicitly install untyped modules, and they somehow do not show up in 'npm ls' typings search x # see if module has a typing registry npm i -D @types/x Watch for message: deprecated... you don't need @types/x installed! Import like: import x from "y"; If not then x will be an object. If you run npx without loading the tsconfig.json file then you must switch the import statements from the above to: import * as x from "y"; Otherwise x will be undefined (at runtime). See: https://javascript.plainenglish.io/how-to-correctly-use-typescript-module-import-syntax-and-settings-in-various-circumstances-e98bfa87f70f IF a non-typed module has no @types registration then you must typeify it manually: https://medium.com/@steveruiz/using-a-javascript-library-without-type-declarations-in-a-typescript-project-3643490015f3 section 'Plan C'. You do need to explicitly install the non-typed module. You need to add entry to a "anything.d.ts" file: declare module "my-untyped-module" "decs.d.ts" must be located in a tsconfig.json-included directory (or dedicated filepath element). + needed for ts-node: Add to tsconfig.json: (per https://stackoverflow.com/questions/51610583/ts-node-ignores-d-ts-files-while-tsc-successfully-compiles-the-project ) "ts-node": { "files": true}, --------------------------------------------------------------------------- Remainder of this file is about... LANGUAGE: To override default "infer" typing, add a : type suffix to variable NAMEs in declarations: let firstName: string = "3"; // type names here are lower-case By default if tsc can't infer to a single type it will set to 'any' pseudo-type, but I override with tsconfig setting 'noImplŃ–citAny'. If noImplicitAny then to allow any (like for JSON.parse) need to specify like: const object: JSON.parse("{}"); 'unknown' pseudo-type is very similar to 'any' but I think allows you to cast with "as"??? Additional native types: any unknown undefined only useful if tsconfigjson 'strictNullChecks is set let y: undefined = undefined; null only useful if tsconfigjson 'strictNullChecks is set let z: null = null; Arrays: Array element type is inferred if you intialize it with any value. Otherwise specify element type like: const names: type[] = []; Can add 'readonly' before the type, for the obvious purpose. I guess can't do this if infer?? Array accesses never allow undefined unless you enable noUncheckedIndexedAccess. Tuple is an Array with fixed length and element-specific typing: let ourTuple: [number, boolean, string] With optional annotation comments: let outTuple: [x: number, b: boolean... For some damned reason only assignments (not push, etc.) are type-constrained, so usually specify readonly before the types: const ourTuple: readonly [... Object member types are inferred but can be overriden like: ? attr name suffix means optional attr const car: { type: string, year?: number} = { type: "Toyota", year: 2009 }; Index Signatures: for runtime-generated attributes: const nameAgeMap: { [index: string]: number } = {}; // ??? Enums: vals default to numbers; only other val type supported is string if you specify a string value. enum CD { C1 [= n0], C2 [=n1], C3 [=n2] } n0 defaults to 0; n1 defaults to n0+1, etc. interface Iface { Object type-spec per above }. Named-Object-type-spec. Can extend: interface Subfac extens OtherIface {... type NewType = existing_type_to_alias OR { Named-Object-type-spec } OR (param-typespec) => ret-type Return type and param typing: function multiply(a: number = 4, b?: number): void|type {...} ? param name suffix means optional If both type and = default value specified then assigment comes after the type spec. Return type defaults to any. Union: function x(code: string | number) {...} // Just an OR for input param types I guess use 'as' casting to use type-specific operatins on the para val? Casting: 'as'== does NOT do any data conversion like say Number(x); it just allows type-specifc operations, and you will usually get a compile-time error where value not applicable. Classes. ES6 classes + Visibility modifier before member name and param names. public OR private OR protected reaonly optional allowed between visibility modifier and member name. Can auto-define instance members by adding a visibility modifier to constructor param names. can: implements InterfaceName to override a superclass member add override after visibility modifier. Only useful if noImplicitOverride abstract class, and abstract after member visibility modifier have the obvious purposes. Generics are very similar to Java generics. Utility Types: Readonly is means all members of Object-type-spec are readonly. All other utility types are used with keyof Iface: all keys of the Interface. Can get type of the mapping with [x]: value syntax.