Skip to content

Civet

The Modern Way to Write TypeScript

Expressive Syntax and Faster Coding with Civet

Civet logo

Civet is a programming language that compiles to TypeScript or JavaScript, so you can use existing tooling but enable concise and powerful syntax. In addition to 99% JS/TS compatibility, there are many features, with some highlights below and more comprehensive examples in the reference. See also Civet's design philosophy.

Highlights: Beyond TC39

Civet code on the lefttop, compiled TypeScript output on the rightbottom.

Pattern Matching

TC39 Proposal: Pattern Matching

switch x
  0
    console.log("zero")
  /^\s+$/
    console.log("whitespace")
  [{type: "text", content}, ...rest]
    console.log("leading text", content)
if (x === 0) {
  console.log("zero");
} else if (
  typeof x === "string" &&
  /^\s+$/.test(x)
) {
  console.log("whitespace");
} else if (
  Array.isArray(x) &&
  x.length >= 1 &&
  typeof x[0] === "object" &&
  x[0] != null &&
  "type" in x[0] &&
  x[0].type === "text" &&
  "content" in x[0]
) {
  const [{ type, content }, ...rest] = x;
  console.log("leading text", content);
}

Pipelines

TC39 Proposal: Pipe Operator

data
  |> Object.keys
  |> console.log
console.log(Object.keys(data));

Pipe expression with shorthand functions:

a |> & + 1 |> bar
bar(a + 1);

Single-Argument Function Shorthand

x.map .name
x.map &.profile?.name[0...3]
x.map &.callback a, b
x.map &+1
x.map -&
x.map(($) => $.name);
x.map(($1) => $1.profile?.name.slice(0, 3));
x.map(($2) => $2.callback(a, b));
x.map(($3) => $3 + 1);
x.map(($4) => -$4);

Custom Infix Operators

operator {min, max} := Math
value min ceiling max floor
const { min, max } = Math;
max(min(value, ceiling), floor);

Declarations in Conditions and Loops

if match := regex.exec string
  console.log match
let ref;
if ((ref = regex.exec(string))) {
  const match = ref;
  console.log(match);
}

Everything is an Expression

items = for item of items
  if item.length
    item.toUpperCase()
  else
    "<empty>"
items = (() => {
  const results = [];
  for (const item of items) {
    if (item.length) {
      results.push(item.toUpperCase());
    } else {
      results.push("<empty>");
    }
  }
  return results;
})();
return
  if x == null
    throw "x is null"
  else
    log `received x of ${x}`
    x.value()
return x == null
  ? (() => {
      throw "x is null";
    })()
  : (log(`received x of ${x}`), x.value());

TC39 proposal: do expressions

x = do
  const tmp = f()
  tmp * tmp + 1
x = (() => {
  {
    const tmp = f();
    return tmp * tmp + 1;
  }
})();

Dedented Strings and Templates

TC39 Proposal: String Dedent

text = """
  This text is a string that doesn't include
  the leading whitespace.
"""
text = `This text is a string that doesn't include
the leading whitespace.`;
text = ```
  Also works for
  ${templates}!
```
text = `Also works for
${templates}!`;

Chained Comparisons

a < b <= c
a is b is not c
a instanceof b not instanceof c
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);
}
for (const item of [1, 2, 3, 4, 5]) {
  console.log(item * item);
}

Spread in Any Position

Spreads in first or middle position:

[...head, last] = [1, 2, 3, 4, 5]
([...head] = [1, 2, 3, 4, 5]),
  ([last] = head.splice(-1));
{a, ...rest, b} = {a: 7, b: 8, x: 0, y: 1}
({ a, b, ...rest } = { a: 7, b: 8, x: 0, y: 1 });
function justDoIt(a, ...args, cb) {
  cb.apply(a, args)
}
function justDoIt(a, ...args) {
  let [cb] = args.splice(-1);
  return cb.apply(a, args);
}

Import Syntax Matches Destructuring

import {X: LocalX, Y: LocalY} from "./util"
import { X as LocalX, Y as LocalY } from "./util";

Export Convenience

export a, b, c from "./cool.js"
export x = 3
export { a, b, c } from "./cool.js";
export var x = 3;

JSX

function Listing(props)
  <h1 #heading>Hello Civet!
  <ul .items>
    <For each=props.items>
      (item) =>
        <li .item {props.style}><Item {item}>
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!

Support the future development of Civet!

Contributors

Thank you for your work and dedication to the Civet project!

Civet v0.6.38