ryanrasti/typenix
{ "createdAt": "2026-03-07T22:12:48Z", "defaultBranch": "main", "description": "Full typing for Nix based on TypeScript", "fullName": "ryanrasti/typenix", "homepage": "", "language": "Go", "name": "typenix", "pushedAt": "2026-03-12T02:21:10Z", "stargazersCount": 267, "topics": [ "nix", "typescript" ], "updatedAt": "2026-03-20T00:16:01Z", "url": "https://github.com/ryanrasti/typenix"}TypeNix
Section titled “TypeNix”Full TypeScript-grade typing for the Nix language — autocomplete, type errors,
hover, go-to-definition — directly in .nix files with no transpilation step.
Parses and type-checks all 42,298 nixpkgs files in 13 seconds without crashing — and where types exist or can be automatically inferred by TypeScript, they’re correct.
![TypeNix demo]!(demo.gif)
Example
Section titled “Example”# @ts: { lib: Lib; stdenv: Stdenv; [key: string] !: any }{ lib, stdenv }:
let version = lib.concatStringsSep "." [ "1" "0" "0" ]; isLinux = stdenv.hostPlatform.isLinux; greeting = lib.optionalString isLinux "Hello from Linux!";
# ❌ error TS2345: Argument of type 'number' is not assignable # to parameter of type 'boolean'. bad = lib.optionalString 42 "oops";instdenv.mkDerivation { pname = "example"; inherit version; src = ./.;}See [examples/starter/]!(./examples/starter/) for a runnable project.
Installation
Section titled “Installation”VSCode extension:
Section titled “VSCode extension:”code --install-extension $(nix build github:ryanrasti/typenix#vscode-extension --print-out-paths)/typenix.vsixNeovim:
Section titled “Neovim:”Put this in lsp/typenix.lua at the root of your Neovim config:
---@type vim.lsp.Configreturn { cmd = function(dispatchers) local cmd = "typenix" return vim.lsp.rpc.start({ cmd, "--lsp", "--stdio" }, dispatchers) end, root_markers = { "flake.nix", ".git" }, filetypes = { "nix", "nixts", },}Then enable it as any other lsp. For nixts filetype for .nix.d.ts files:
vim.filetype.add({ pattern = { [".*/*.nix.d.ts"] = "nixts", },})vim.treesitter.language.register("typescript", { "nixts" })Run directly:
Section titled “Run directly:”# needs a tsconfig.json pointing at your .nix filesecho '{"include": ["**/*.nix"]}' > tsconfig.json
nix run github:ryanrasti/typenix -- --noEmitHow It Works
Section titled “How It Works”TypeNix is a fork of tsgo
(the TypeScript compiler in Go). When it encounters a .nix file:
- tree-sitter-nix parses it
- The tree-sitter AST is converted into the same TypeScript AST nodes that the TS parser produces
- The standard TypeScript binder, checker, and LSP work essentially unchanged
.nix file → tree-sitter-nix → TS AST → binder → checker → LSP.ts file → TS scanner/parser → TS AST → binder → checker → LSP ↑ same types, same pipelineThe result: the full TypeScript type system applied to Nix — with special handling for:
- Fixed-point/overrides:
classannotation converts(self: { ... })patterns into a TypeScript class, with full self-referential typing - Existing
::type annotations from nixpkgslib/automatically parsed and used ./foo.nixpaths carry their import type, are hoverable and followable via LSP- Bundled types for
Lib,Stdenv,Platform,Derivation, and allpkgs/by-namepackages
Type Annotations
Section titled “Type Annotations”Use # @ts: comments to annotate nix expressions with TypeScript types:
# @ts: { lib: Lib; stdenv: Stdenv; [key: string] !: any }{ lib, stdenv }:Available types (no imports needed):
Nixpkgs— top-level pkgs objectLib— all nixpkgs lib functions (lib.concatStringsSep,lib.optionalString, etc.)Stdenv—mkDerivation,hostPlatform,cc, etc.Platform—isLinux,isDarwin,system, etc.Derivation— standard derivation output type
Building
Section titled “Building”nix build .#typenix # CLI binarynix build .#vscode-extension # VS Code extension (includes binary)Current State
Section titled “Current State”TypeNix is a proof of concept. It is usable on real nix/nixpkgs code:
- Typing for builtins,
lib,stdenv.mkDerivation,import, many packages on theNixpkgstype - ~50 type errors remaining in nixpkgs itself (down from thousands)
- Fixed-point self-references translated as TypeScript classes allowing for typed self-reference
- VS Code extension with hover, go-to-definition, autocomplete
Limitations:
- Many places in nixpkgs need explicit typing to be useful (right now they are implicitly
any) noImplicitAny: falsein tsconfig.json: ~1k suppressed errors from circular references and variations on the fixed-point structurepkgs/by-nameentries are autogenerated — fine-grained types require actually typing the individual files
The above are known, scoped, fixable problems.
Contributing
Section titled “Contributing”The best place to start are PRs for the above or other ergonomic fixes. PRs should be:
- Tested
- Scoped to a single fix / feature
Issues without an accompanying PR are handled on a best-effort basis.
Nix (the model) vs. Nix (the language):
- Nix (the model): the only sane way to handle system dependencies. 100% the right approach.
- Nix (the language): a bespoke runtime that served the model well, but suffers from a lack of modern tooling and is unfamiliar to most developers.
Nix (the language) is holding Nix (the model) back from widespread adoption. TypeNix is a step to unleash it.
What’s Next
Section titled “What’s Next”TypeNix is the first step in unifying the best of the Nix and TypeScript ecosystems. If you are interested follow on X or Github.
License
Section titled “License”Apache-2.0 (inherited from typescript-go)