Expressions and types
A type claim is erased, a shape the GPU has a word for is kept, and a value TypeScript would build at run time is refused where it is written.
-
Destructuring
One declaration per name, in the order written.
TypeScript export function swapped(v: vec2): vec2 {const { x, y } = vreturn vec2(y, x)}Emitted WGSL fn swapped(v: vec2<f32>) -> vec2<f32> {let x = v.x;let y = v.y;return vec2<f32>(y, x);} -
Object spread
One read per field of the struct, with the fields written after it over them.
TypeScript export function lifted(p: Point): Point {return { ...p, y: 9. }}Emitted WGSL fn lifted(p: Point) -> Point {return Point(p.x, 9.0);} -
Array literal
An array initializer, and only where the declaration states
array<T, N>. array-literal-rampTypeScript export function step3(i: i32): f32 {const xs: array<f32, 3> = [0.15, 0.5, 0.9]return xs[i]}Emitted WGSL fn step3(i: i32) -> f32 {let xs = array<f32, 3>(0.15, 0.5, 0.9);return xs[i];} -
Tuple
A tuple is an array of a length the type fixes, a return included. tuple-and-brand
TypeScript export function bounds(x: f32): [f32, f32] {return [x - 1., x + 1.]}Emitted WGSL fn bounds(x: f32) -> array<f32, 2> {return array<f32, 2>((x - 1.0), (x + 1.0));} -
Literal union
A union whose members all name one type names that type.
TypeScript export function isWire(m: 0 | 1 | 2): bool {return m === 2}Emitted WGSL fn isWire(m: i32) -> bool {return (m == 2);} -
Branded type
The brand is erased and the parameter is an
f32. tuple-and-brandTypeScript type Metres = f32 & { readonly [m]: 'metres' }Emitted WGSL fn deeper(d: f32) -> f32 {return (d * 2.0);} -
Type claims
A claim about a type, not a conversion, so each emits what its operand emits.
TypeScript export function claimed(x: f32): f32 {const a = x as f32const b = (x satisfies f32)!const k = 2. as constreturn a + b * k}Emitted WGSL fn claimed(x: f32) -> f32 {return (x + (x * 2.0));} -
Exponent operator
powon both targets.TypeScript export function curved(x: f32): f32 {return x ** 2.2}Emitted WGSL fn curved(x: f32) -> f32 {return pow(x, 2.2);} -
&&on aboolThe operator both targets have, on one
boolat a time.TypeScript export function both(a: bool, b: bool): bool {return a && b}Emitted WGSL fn both(a: bool, b: bool) -> bool {return (a && b);} -
Refused&&on a maskCombine masks with
all,anyor aselect. bool-selectTypeScript export function both(a: vec2b, b: vec2b): bool {return a && b}Compiler diagnostic
TS8003 Logical "&&" requires bool operands.
-
Optional field
RefusedA struct field is always there in the memory the host fills.
TypeScript class Disc {center: vec2radius?: f32}Compiler diagnostic
TS8010 Optional field "radius?" on "Disc" is not supported: a struct field is always present in the buffer the host fills.
-
String value
RefusedThere is no string on the GPU; write the cases as an enum.
TypeScript export function label(x: f32): f32 {const name = `band ${x}`return x}Compiler diagnostic
TS8013 Template strings are JS. TypeShade has no string type.
-
RefusednumberA number on the GPU has a width.
TypeScript export function twice(x: number): number {return x * 2}Compiler diagnostic
TS8002 A number on the GPU has a width. Write f32 for a float, i32 or u32 for an integer.
-
RefusedbooleanThe shader spelling is
bool.TypeScript export function on(x: boolean): f32 {return x ? 1. : 0.}Compiler diagnostic
TS8002 TypeShade spells the boolean "bool".
-
Integer literal
An integer-written local initializer can take the
i32oru32required by a declared nongeneric function, a constructor or a method argument. Explicitly typed initialization and simple assignment can establish the same demand in either direction when the type is known independently of the local. Conflicting concrete types produceTS8003; use an annotation or cast to settle the type. With no integer demand, an unannotated local remainsf32. Float-written initializers, module constants and loop induction variables keep their existing rules.TypeScript class Hit {constructor(public index: i32) {}offset(value: i32): i32 { return this.index + value; }}export function counts(): i32 {let n = -1;const hit = new Hit(n);n = hit.index;return hit.offset(n);}Emitted WGSL fn Hit_new(index: i32) -> Hit {var self_: Hit = Hit(0);self_.index = index;return self_;}fn Hit_offset(self_: Hit, value: i32) -> i32 {return (self_.index + value);}fn counts() -> i32 {var n: i32 = -1;let hit = Hit_new(n);n = hit.index;return Hit_offset(hit, n);} -
Increment and decrement
An assignment of the value one step on.
TypeScript export function stepped(x: f32): f32 {let acc: f32 = xacc++acc--return acc}Emitted WGSL fn stepped(x: f32) -> f32 {var acc: f32 = x;acc = (acc + 1.0);acc = (acc - 1.0);return acc;}