Civet
The Modern Way to Write TypeScript
Concise Syntax and Faster Coding with Civet

Civet on the lefttop, compiled TypeScript output on the rightbottom:
Highlights: Beyond TC39
Pipelines
data
|> Object.keys
|> console.log
Edit inline or edit in the Playground!
console.log(Object.keys(data));
Pipe expression with shorthand functions:
a |> & + 1 |> bar
Edit inline or edit in the Playground!
bar((($) => $ + 1)(a));
Dedented Strings and Templates
text = """
This text is a string that doesn't include the leading
whitespace.
"""
Edit inline or edit in the Playground!
text = `This text is a string that doesn't include the leading
whitespace.`;
text = ```
Also works for
templates!
```
Edit inline or edit in the Playground!
text = `Also works for
templates!`;
Chained Comparisons
a < b <= c
a is b is not c
a instanceof b not instanceof c
Edit inline or edit in the Playground!
a < b && b <= c;
a === b && b !== c;
a instanceof b && !(b instanceof c);
Default to const
for Iteration Items
for (item of [1, 2, 3, 4, 5]) {
console.log(item * item);
}
Edit inline or edit in the Playground!
for (const item of [1, 2, 3, 4, 5]) {
console.log(item * item);
}
Modulo Operator
let a = -3
let b = 5
let rem = a % b
let mod = a %% b
console.log rem, mod
Edit inline or edit in the Playground!
const modulo: (a: number, b: number) => number = (
a,
b
) => ((a % b) + b) % b;
let a = -3;
let b = 5;
let rem = a % b;
let mod = modulo(a, b);
console.log(rem, mod);
Spread in Any Position
Spreads in first or middle position:
[...head, last] = [1, 2, 3, 4, 5]
Edit inline or edit in the Playground!
const splice: <T>(
this: T[],
start: number,
deleteCount?: number
) => T[] = [].splice as any;
([...head] = [1, 2, 3, 4, 5]),
([last] = splice.call(head, -1));
{a, ...rest, b} = {a: 7, b: 8, x: 0, y: 1}
Edit inline or edit in the Playground!
({ a, b, ...rest } = { a: 7, b: 8, x: 0, y: 1 });
function justDoIt(a, ...args, cb) {
cb.apply(a, args)
}
Edit inline or edit in the Playground!
const splice: <T>(
this: T[],
start: number,
deleteCount?: number
) => T[] = [].splice as any;
function justDoIt(a, ...args) {
let [cb] = splice.call(args, -1);
return cb.apply(a, args);
}
Import Syntax Matches Destructuring
import {X: LocalX, Y: LocalY} from "./util"
Edit inline or edit in the Playground!
import { X as LocalX, Y as LocalY } from "./util";
Export Convenience
export a, b, c from "./cool.js"
export x = 3
Edit inline or edit in the Playground!
export { a, b, c } from "./cool.js";
export var x = 3;
Single-Argument Function Shorthand
x.map &.name
x.map &.profile?.name[0...3]
x.map &.callback a, b
x.map +&
Edit inline or edit in the Playground!
x.map(($) => $.name);
x.map(($1) => $1.profile?.name.slice(0, 3));
x.map(($2) => $2.callback(a, b));
x.map(($3) => +$3);
INFO
Short function block syntax like Ruby symbol to proc, Crystal, or Elm record access
Custom Infix Operators
operator {min, max} := Math
value min ceiling max floor
Edit inline or edit in the Playground!
const { min, max } = Math;
max(min(value, ceiling), floor);
Everything is an Expression
items = for item of items
if item.length
item.toUpperCase()
else
"<empty>"
x == null ? throw "x is null" : x.fn()
Edit inline or edit in the Playground!
items = (() => {
const results = [];
for (const item of items) {
if (item.length) {
results.push(item.toUpperCase());
} else {
results.push("<empty>");
}
}
return results;
})();
x == null
? (() => {
throw "x is null";
})()
: x.fn();
JSX
function Listing(props)
<h1 #heading>Hello Civet!
<ul .items>
<For each=props.items>
(item) =>
<li .item {props.style}><Item {item}>
Edit inline or edit in the Playground!
function Listing(props) {
return (
<>
<h1 id="heading">Hello Civet!</h1>
<ul class="items">
<For each={props.items}>
{(item) => {
return (
<li
class="item"
style={props.style}
>
<Item item={item} />
</li>
);
}}
</For>
</ul>
</>
);
}
Sponsors
Thank you to all of our sponsors for your invaluable support and contribution to the Civet language!
Contributors
Thank you for your work and dedication to the Civet project!