@danielx/civet

中文文档
0.11.16发布于 2026/08/22MITTypeScriptESM + CJS构建来源已验证近 30 天下载 5854

CoffeeScript style syntax for TypeScript

原始使用文档
文档目录16 节
  1. Quickstart Guide
  2. Code Sample
  3. Overview
  4. Implementations of New and Proposed ES Features
  5. Convenience for ES6+ Features
  6. JSX Enhancements
  7. TypeScript Enhancements
  8. Changes from ES6
  9. Scripting Improvements
  10. Comparison to CoffeeScript
  11. Directives
  12. Using Civet in your Node.js Environment
  13. Testing
  14. Developing
  15. Building
  16. Sponsorship

Civet

Build Status NPM Version NPM Downloads Coverage Status Discord Open Collective

The modern way to write TypeScript.

Quickstart Guide

# Install
npm install -g @danielx/civet
# Run Civet code directly in a REPL
civet
# Transpile typed Civet code into TypeScript in a REPL
civet -c
# Compile Civet source file to TypeScript
civet < source.civet > output.ts
# Execute a .civet script
civet source.civet ...args...
# Execute a .civet source file in node
node --import @danielx/civet/register source.civet
# Type check entire project, which requires TypeScript installed
npm install -g typescript
civet --typecheck

image

Code Sample

ts, {CompilerOptions} from typescript

DefaultCompilerOptions : CompilerOptions :=
  allowNonTsExtensions: true
  allowJs: true
  target: ts.ScriptTarget.Latest
  moduleResolution: ts.ModuleResolutionKind.NodeJs
  module: ts.ModuleKind.CommonJS
  allowSyntheticDefaultImports: true
  experimentalDecorators: true

fileCache : Record<string, any> := {}

createCompilerHost := (options: CompilerOptions, moduleSearchLocations : string[]) ->
  fileExists := (fileName: string) : boolean ->
    fileCache[fileName]?

  readFile := (fileName: string) ->
    fileCache[fileName]

Overview

Civet is essentially a tasteful superset of TypeScript.

Implementations of New and Proposed ES Features

See the documentation for examples of these and other features.

  • Pattern matching (based on TC39 proposal)
    • switch can match patterns like [{type: "text", name}, ...rest]
  • Pipe operator (based on F# pipes, Hack pipes and the TC39 proposal)
    • data |> Object.keys |> console.log equivalent to console.log(Object.keys(data))
    • Use single-argument arrow functions or & shorthand to specify how to use left-hand side
    • |> await, |> yield, and |> return (at end) for wrapping left-hand side with that operation
  • Short function block syntax like Ruby symbol to proc, Crystal, Elm record access
    • Access: x.map &.name or x.map .name → x.map(a => a.name)
    • Nested access + slices: x.map &.profile?.name[0...3] → x.map(a => a.profile?.name.slice(0, 3))
    • Function call: x.map &.callback a, b → x.map($ => $.callback(a, b))
    • Unary operators: x.map !!& → x.map($ => !!$)
    • Binary operators: x.map &+1 → x.map($ => $+1)
  • Object literal shorthand
    • {foo()} → {foo: foo()}, {props.foo} → {foo: props.foo}
    • {`${x}${y}`: z} → {[`${x}${y}`]: z}
    • data.{x,y} or data{x,y} → {x: data.x, y: data.y}
    • Flagging shorthand based on from LiveScript: {+debug, -live, !verbose} → {debug: true, live: false, verbose: false}
  • Custom infix operators from any two-argument function
  • do expressions, if expressions, for expressions

Convenience for ES6+ Features

  • Const assignment shorthand: a := b → const a = b, {a, b} := c → const {a, b} = c
  • Let assignment shorthand: a .= b → let a = b
  • Typed versions of above: a: number .= 5 → let a: number = 5 (but note that a: number = 5 is the object literal {a: (number = 5)}).
  • @#id → this.#id shorthand for private identifiers
  • import shorthand: x from ./x → import x from "./x"
  • Dynamic import shorthand: import './x' not at top level (e.g. await import './x' or inside a function) → import('./x')
  • Optional import rename syntax that corresponds to destructuring rename import {x: y} from "./z" → import {x as y} from "./z". You can still use as to be compatible with existing ES imports.
  • export shorthand: export x, y → export {x, y}
  • Triple backtick Template Strings remove leading indentation for clarity
  • Class constructor shorthand @( ... )
  • ClassStaticBlock @ { ... }
  • < as extends shorthand
  • /// Block RegExp like Python re.X

JSX Enhancements

Inspired by solid-dsl discussions and jsx spec issues

  • Indentation: instead of explicitly closing <tag>s or <>s, you can indent the children and Civet will close your tags for you
  • Multiple adjacent elements and/or fragments get automatically combined into a fragment.
  • Arrow function children do not need to be wrapped in braces (assuming they are not preceded by text); this is unambiguous because > isn't valid JSX text. For example, <For> (item) => ... (where function body can be indented).
  • #foo shorthand for id="foo"; also #"foo bar", #`foo ${bar}`, #{expr}
  • .foo shorthand for class="foo" (but must be at least one space after tag name); also .foo.bar, ."foo bar", .`foo ${bar}`, .{expr}
    • "civet react" flag uses className instead of class
  • +foo shorthand for foo={true}, -foo/!foo shorthand for foo={false}
  • Any braced object literal can be used as an attribute: {foo} → foo={foo}, {foo: bar} → foo={bar}, {...foo} remains as is; methods and getters/setters work too.
  • Attribute ...foo shorthand for {...foo}
  • Attribute values without whitespace or suitably wrapped (parenthesized expressions, strings and template strings, regular expressions, array literals, braced object literals) do not need braces: foo=bar → foo={bar}, count=count() → count={count()}, sum=x+1 → sum={x+1}, list=[1, 2, 3] → list={[1, 2, 3]}
  • Attributes can use computed property names: [expr]={value} → {...{[expr]: value}}
  • "civet solid" flag adds correct types for JSX elements and fragments. Use "civet solid client" (default) for client-only code, "civet solid server" for server-only code (SSR only), or "civet solid client server" for isomorphic code that runs on client and server (SSR + hydration).
  • XML comments: <!-- ... --> → {/* ... */}

TypeScript Enhancements

Changes from ES6

  • Implicit returns, even for multi-statement functions (avoid by specifying a void return type, adding a trailing ; or explicit return, or via the directive "civet -implicitReturns")
  • Disallow no parens on single argument arrow function. x => ... must become (x) => ... The reasoning is x -> ... => x(function() ...) in CoffeeScript and having -> and => behave more differently than they already do is bad. Passing an anonymous function to an application without parens is also convenient.
  • for(i of x) ... defaults to const declaration → for(const i of x) ...
  • Disallow comma operator in conditionals and many other places. if x, y is not allowed. But for i = 0, l = a.length; i < l; i++, i *= 2 is allowed.
  • Comma operator in case/when instead becomes multiple conditions.
  • Numbers can't end with a dot (otherwise would be ambiguous with CoffeeScript slices y[0..x]). This also implies that you can't access properties of numbers with 1..toString() use 1.toString() instead. When exponent follows a dot it is treated as a property access since an exponent could be a valid property 1.e10 → 1..e10. The workaround is to add a trailing zero 1.0e10 or remove the dot before the exponent 1e10.
  • Additional reserved words and, or, loop, until, unless
  • Experimental decorator syntax is @@ instead of @ because @ is premium real estate and @id → this.id, and @ is also static fields/methods, etc.
    @@classDecorator
    class X
      @@methodDecorator
      method() {}
    
  • when inside switch automatically breaks and adds block scope.
  • else inside switch adds block scope.
  • No whitespace between unary operators and operands. Mandatory whitespace between condition and ternary ? ex. x ? a : b since x? is the unary existential operator.
  • Labels written :label (except for special case $: for Svelte)

Scripting Improvements

  • Shebang line is kept unmodified in output
    #!./node_modules/.bin/ts-node
    console.log "hi"
    

Comparison to CoffeeScript

Take a look at this detailed Civet // CoffeeScript comparision

Directives

Civet is not just one language; it can be configured in a variety of ways via directives to add or remove language features, or improve behavior in certain environments. See config documentation.

Using Civet in your Node.js Environment

You have now been convinced that Civet is right for your current/next project. Here is how to set up your environment to get productive right away and have a Good Time℠.

Testing

Code coverage with c8 "just works" thanks to their source map integration and Civet's source maps.

c8 + Mocha

package.json

  "scripts": {
    "test": "c8 mocha",
    ...
  },
  "c8": {
    "extension": [
      ".civet"
    ]
  },
  "mocha": {
    "extension": [
      "civet"
    ],
    "loader": [
      "@danielx/civet/esm"
    ],
    ...
  ...

If you don't care for code coverage you can skip c8 (but it is so easy why not keep it?).

You can also add .js and .ts extensions if you want to mix and match! Even .coffee will work if you require coffeescript/register or add a loader for it.

Execute the tests

pnpm test

Step 4: Enjoy!

Developing

Use the alpha version of Civet Language Server

The language server provides syntax highlighting, completions, hover documentation, symbols outline, red squigglies, and go to definition.


Q? Why can't I just use the built-in VSCode TypeScript LSP?

A: VSCode's built in TypeScript LSP can't resolve non .ts/.js, not even with plugins. Maybe one day they'll allow for plugins that let you adjust the resolver and insert a transpilation step but until then a separate language server is necessary.


Q? Sometimes the file outline disappears and the red squigglies are all in the wrong place and maybe a notification pops up about some kind of LSP error.

A: I'm sorry that happened to you but the Civet Language Server is still alpha and improving rapidly. Please let me know exactly what happened and I'll try to do better next time.

It may happen when there is a syntax error in your Civet file. You can check and see if it compiles using the CLI tool in the meantime.

Please do submit bug reports / feature requests.

Building

I strongly recommend using esbuild for building / packaging your Civet project.

import esbuild from 'esbuild'
import civetPlugin from '@danielx/civet/esbuild'

esbuild.build({
  ...,
  plugins: [
    civetPlugin({ ts: 'preserve' })
  ]
}).catch(() => process.exit(1))

It's super fast and works great!

Sponsorship

If you are so inclined, you can sponsor Civet on Open Collective.

版本与发布记录

@danielx/civet 共发布 368 个版本,首次发布于 2022/08/24;过去 12 个月发布了 16 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.11.16latest2026/08/222 个月前
0.11.152026/07/213 个月前
0.11.142026/06/274 个月前
0.11.132026/06/055 个月前
0.11.122026/05/275 个月前
0.11.112026/05/255 个月前

关于 @danielx/civet 的常见问题

@danielx/civet 是什么?

CoffeeScript style syntax for TypeScript

如何安装 @danielx/civet?

在项目目录运行 npm install @danielx/civet,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 civet,可以用 npx civet 直接运行。

@danielx/civet 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@danielx/civet 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@danielx/civet 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=19 || ^18.6.0 || ^16.17.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@danielx/civet 可以商用吗?

@danielx/civet 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@danielx/civet 的下载量有多少?

根据 npm 官方下载统计,@danielx/civet 在 2026/10/12 – 2026/11/10 这 30 天内被下载 5,854 次,日均约 195 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@danielx/civet 还在维护吗?

最新版本 0.11.16 发布于 2026/08/22(2 个月前);至今共发布 368 个版本,其中过去 12 个月发布了 16 个;首次发布于 2022/08/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。