Tish vs JavaScript
What differs from JavaScript and what is additional in Tish.
This page documents how Tish differs from JavaScript and what Tish adds. Since Tish is not pure JS, developers coming from JS/TS need this reference.
Differences from JavaScript
Additions (Tish-specific)
Semantic Details
No undefined
Tish has only null. Optional chaining (?.) and missing properties return null where JavaScript returns undefined. Because of this, typeof null returns "null" in Tish, unlike JavaScript where it returns "object".
Strict equality only
Loose equality (==) is not supported. Use === and !== only. There is no implicit type coercion in comparisons.
No this, with, eval
Tish omits these for security and compileability. Pass explicit parameters instead of relying on this.
No prototypes
Objects and arrays are plain data structures. No Object.create, prototype chain, or instanceof.
No classes or super
There is no class syntax and no super. Use plain objects and functions.
new expressions (limited)
Tish accepts new (including argument lists and spread) like JavaScript syntax, but without class there are no user-defined class constructors in the JS sense. On the VM, interpreter, and native Rust output, construction uses a host construct path (roughly: call a plain function value with the args, or an object constructor exposed via an internal __construct hook), not full ECMA [[Construct]] — no this binding, no prototype wiring, and still no instanceof. Some builtins are approximations (for example, new Uint8Array(n) may yield a numeric array of zeros rather than a real typed byte buffer; some globals like AudioContext are stubs). The interpreter may accept new on a slightly wider set of builtin values than the VM; if you need identical behavior, test your target. With tish build --target js, emitted code uses the engine’s real new (wrapped with ?? null for Tish’s null rules).
Modules (import / export)
Tish supports import and export for language builtins (e.g. import { serve } from 'http' with the http feature), native module specs such as tish:fs, tish:http, tish:process, tish:ws, etc. on the Rust native compile path, and multi-file programs where the resolver is enabled. tish:* and npm-linked native modules require tish build --native-backend rust (not the Cranelift/LLVM “embedded bytecode only” binary paths). This is not “every npm package on every target”; dynamic import() / import.meta are out of scope for ECMA alignment in the same way as in the main Tish docs.
Async/await support
Tish supports async fn and await for asynchronous I/O. Use await fetch(...) and await fetchAll(...) for HTTP (both return Promises). Promises (ECMA-262 Promise objects) are supported: Promise(executor), .then, .catch, .finally, Promise.resolve, Promise.reject, Promise.all, Promise.race. Host APIs setTimeout, setInterval, clearTimeout, and clearInterval are non-blocking (callbacks run after the delay; setTimeout returns immediately). Generators are not supported.
See also
- ECMA Alignment — Mapping to ECMA-262
- JS Compatibility Gaps — Implementation gaps requiring workarounds
- Builtins Overview — Feature flags and secure-by-default