Overview of tsgo-client
maintsgo-client is a Rust client library designed to communicate with TypeScript Go (tsgo) processes. It provides a high-level API to spawn these processes and facilitate the loading and analysis of TypeScript projects.repository·main·Indexed 19 days ago
https://github.com/web-infra-dev/rslintA high-performance, ESLint-compatible linter for JavaScript and TypeScript powered by typescript-go. Documentation covers the core linting engine, the rslint-wasm browser package, the VS Code extension, and the internal inspector module used for AST, type, symbol, and data flow analysis.
tsgo-client is a Rust client library designed to communicate with TypeScript Go (tsgo) processes. It provides a high-level API to spawn these processes and facilitate the loading and analysis of TypeScript projects.Rslint is a high-performance, ESLint-compatible linter for JavaScript and TypeScript. It is powered by typescript-go, providing 20-40x faster performance compared to traditional ESLint setups.
Key features include:
typescript-eslint configurations.Rslint is a high-performance JavaScript and TypeScript linter designed as a drop-in replacement for ESLint and TypeScript-ESLint. It is built to provide 20-40x speedup over traditional ESLint setups by using a Go implementation and integrating with typescript-go for native parsing and direct TypeScript AST usage.
typescript-go integration.typescript-go.rslint-wasm package provides a WebAssembly (WASM) build of Rslint, allowing you to run Rslint linting logic directly within a web browser environment.The no-standalone-expect rule disallows using expect calls outside of it or test blocks. This prevents assertions that sit directly in a describe block, at module scope, or in other locations where Jest will not execute them as part of a test case.
What is allowed:
expect calls inside helper functions (even if the helper is defined outside the it/test callback), provided the helper is invoked from within a test.expect APIs at module scope, such as expect.any() and expect.extend().What is disallowed:
expect calls directly inside a describe block.expect calls sitting at the top-level module scope.expect.hasAssertions() called at the module scope.// Incorrect
describe('a test', () => {
expect(1).toBe(1);
});
expect(1).toBe(1);
// Correct
describe('a test', () => {
it('an it', () => {
expect(1).toBe(1);
});
});
const helper = () => {
expect(1).toBe(1);
};
describe('a test', () => {
it('an it', () => {
helper();
});
});
expect.any(String);
expect.extend({});The no-hooks rule prevents the use of Jest lifecycle hooks (beforeEach, afterEach, beforeAll, afterAll). This rule is used to enforce isolated and explicit tests, reducing reliance on shared setup/teardown behavior that can make test order and failures difficult to reason about.
Using hooks for setup or teardown:
beforeEach(() => {
setupDatabase();
});
afterAll(() => {
cleanup();
});Performing setup explicitly within the test or using describe blocks for grouping without hooks:
test("works with explicit setup", () => {
const db = createTestDatabase();
expect(runWith(db)).toBe(true);
});
describe("suite", () => {
test("case", () => {
expect(1 + 1).toBe(2);
});
});// Incorrect
beforeEach(() => {
setupDatabase();
});
// Correct
test("works with explicit setup", () => {
const db = createTestDatabase();
expect(runWith(db)).toBe(true);
});The role-supports-aria-props rule ensures that JSX elements using ARIA roles only utilize aria-* properties that are valid for that specific role.
role attribute. If no explicit role is provided, it uses an implicit role table (e.g., <a href="#" /> is treated as role="link").null/undefined values) and checks if any aria-* attribute is supported by the resolved role.<a> only acquires the link role if an href attribute is present, and <img> loses its img role if alt="" is used or if the src contains .svg.role="BUTTON") and ARIA prop names (e.g., aria-Checked) must be lowercase. Mixed-case values will not be validated.{...props}) are opaque and are not validated, even if the object contains aria-* keys.The way autofixes are applied depends on how you are using Rslint:
| Interface | Behavior |
|---|---|
| CLI (default) | Requests diagnostics only; no fixes are constructed. |
CLI --fix | Requests native autofixes; can run multiple passes; uses a final diagnostics-only pass to verify. |
| LSP Quick Fix | Returns direct text edits for a single diagnostic. |
| LSP Fix-all | Runs repeated lint-fix cycles, then returns a single whole-document replacement. |
| LSP API | Requests all native edits (fixes and suggestions) as metadata. |
API (lint({ fix: true })) | Applies fixes in a single pass and returns the fixed source in output. Does not re-lint across passes. |
The no-direct-mutation-state rule prevents developers from directly modifying this.state in React components. Direct mutation bypasses React's ability to schedule re-renders and reconcile the UI.
Key constraints:
this.setState() (for class components) or the setter returned by useState (for functional components).this.state is only permitted inside a component's constructor when seeding the initial state.Component or PureComponent) and ES5 components created via createReactClass.The no-misleading-character-class rule disallows characters whose visual rendering is composed of multiple code points (such as combining marks, surrogate pairs, regional indicators, emoji-modifier sequences, or joined ZWJ sequences) from appearing inside a regex character class [...].
Because these sequences cannot be matched as a single unit by the regex engine, they often produce surprising or incorrect matches. To fix this, you should use the u or v flags, or use Unicode property escapes (e.g., \q{...}) when using the v flag.
// Incorrect: multiple code points in a class without proper flags/handling
/^[Á]$/u; // a + combining acute
/^[👶🏻]$/u; // base emoji + skin tone modifier
/^[👨👩👦]$/u; // ZWJ-joined family sequence
// Correct: using the v-flag to preserve sequences
/^[\q{👶🏻}]$/v;
// Correct: using the u-flag for astral characters
/^[👍]$/u;This rule is designed to be a 1:1 implementation of the eslint-plugin-react rule. Note the following implementation details:
forms: true is enabled, the rule does not provide automatic fixes, matching upstream behavior.rel attribute uses an expression the rule cannot statically analyze (e.g., rel={getRel()}), a diagnostic will be reported, but no autofix will be provided.<form> elements, the rule always treats allowReferrer as false. Even if the rule-level option is true, forms using only rel="noopener" will still trigger a violation.The no-useless-default-assignment rule disallows default values in default parameters or destructuring that will never be used.
In TypeScript, default values are only triggered when the value is undefined. If the source type guarantees a non-undefined value, the default is unreachable code and can be misleading regarding the value's nullability.
// foo is guaranteed to be a string, so the default '' is unreachable
function Bar({ foo = '' }: { foo: string }) {
return foo;
}
// The object literal guarantees 'foo' is 'bar'
const { foo = '' } = { foo: 'bar' };
// The array element is guaranteed to be 'bar'
const [foo = ''] = ['bar'];
// The parameter 'a' is guaranteed to be a number from the map
[1, 2, 3].map((a = 42) => a + 1);
// Explicitly assigning undefined as a default is redundant
function f(a = undefined) {}
const { a = undefined } = {};
function g(p: number | undefined = undefined) {}// foo is optional, so the default is reachable
function Bar({ foo = '' }: { foo?: string }) {
return foo;
}
// The source value is explicitly undefined
const { foo = '' } = { foo: undefined };
// The array contains undefined
const [foo = ''] = [undefined];
// The map includes undefined elements
[1, 2, 3, undefined].map((a = 42) => a + 1);
// Using optional parameters
function f(a?: number) {}
function g(p?: number | undefined) {}