twoslashes v0.0.5
TwoSlashes
A fork and rewrite of @typescript/twoslash, with improvements:
!NOTE Working in progress, breaking changes are expected.
- Unified information interface, consistent and easier to manipulate
createTwoslasher
function to create a twoslash instance with cached language servers (5-20 times faster!)- ESM-first, dual CJS/ESM builds
keepNotations
flag for better support of custom languages (seetwoslash-vue
integration)- Lighter, no longer deps on
lz-string
anddebug
Breaking Changes
Breaking changes from @typescript/twoslash
:
- The returned items have different signatures, and different types of the items (
staticQuickInfo
,queries
,errors
,tags
) are now unified into a single arraynodes
. Learn more at the Information Nodes section. - Main entry point
import "twoslashes"
bundlestypescript
, while a new sub-entryimport "twoslashes/core"
is dependency-free and requires providing your own typescript instance. defaultOptions
is renamed tohandbookOptions
defaultCompilerOptions
is renamed tocompilerOptions
Features
Information Nodes
TwoSlashes returns all types of information in the nodes
array.
With some common properties:
type
: the type of the node. Can behover
,query
,error
,tag
,highlight
orcompletion
(in some entries waskind
in@typescript/twoslash
)start
: the 0-indexed start position of the node in the output codeline
: a 0-indexed line number of the node in the output codecharacter
: a 0-indexed character number of the node in the output code (in some entries it wasoffset
in@typescript/twoslash
)length
: length of the node
For different types of nodes, they have some extra properties:
hover
text
: the text of the hover, usually the type information of the given nodedocs
: the jsdoc of the given node, can beundefined
query
Same as hover
highlight
text
: the extra annotation text of the highlight, can beundefined
completion
completion
: the completion entriescompletionPrefix
: the prefix of the completion
error
text
: the error message (wasrenderedMessage
in@typescript/twoslash
)level
: the error level (wascategory
in@typescript/twoslash
)code
: TypeScript error codeid
: a generated based on the code and position of the error
tag
text
: the text of the tag (wasannotation
in@typescript/twoslash
)
Getters
To make it easier to access, we also provide some getters shortcuts to each type of the nodes:
export interface TwoSlashReturn {
/** The output code */
code: string
/**
* Nodes containing various bits of information about the code
*/
nodes: TwoSlashNode[]
/** Getters */
get hovers(): NodeHover[] // was `staticQuickInfos`
get queries(): NodeQuery[] // was `queries` with `kind: 'query'`
get completions(): NodeCompletion[] // was `queries` with `kind: 'completion'`
get errors(): NodeError[]
get highlights(): NodeHighlight[]
get tags(): NodeTag[]
/**
* The meta information
*/
meta: TwoSlashReturnMeta
}
createTwoSlasher
TwoSlash runs a TypeScript language server to get the information, which could be a heavy operation to load and parse all the files it needs. In repetitive usages, you may not want to initialize the language server every simple time. TwoSlashes provides a createTwoslasher
factory function allows you to cache the language servers and reuse the already initialized files.
import { createTwoSlasher } from 'twoslashes'
const twoslasher = createTwoSlasher({
// you can have some default options here
})
const result1 = twoslasher('import { ref } from "vue"', 'ts')
// the second time will be much faster as the types from `vue` is already
const result2 = twoslasher('import { computed } from "vue"', 'ts')
This would result in a 5-20 times faster performance in repetitive usage.
To avoid getting interference across runs, it will reuse the language server with the same compilerOptions
. Internally it holds a map of hashed compilerOptions
to the language server instances.
You can retrieve the cached map and clear it when necessary, to avoid memory leaks:
import { createTwoSlasher } from 'twoslashes'
const twoslasher = createTwoSlasher()
// do something
// Clear the cached language servers, free the memory
twoSlasher.getCacheMap()?.clear()
Backward Compatibility Layer
To make it easier to migrate from @typescript/twoslash
, TwoSlashes provides a backward compatibility layer that allows you to use the old interface with the new implementation.
import { twoslasherLegacy } from 'twoslashes'
const result = twoslasherLegacy('import { ref } from "vue"', 'ts')
console.log(result.staticQuickInfos) // the old interface
You can also compose it your own by only converting the return value:
import { convertLegacyReturn, twoslasher } from 'twoslashes'
const result = twoslasher('import { ref } from "vue"', 'ts') // new interface
const legacy = convertLegacyReturn(result) // <--
console.log(legacy.staticQuickInfos) // the old interface
Benchmark
twoslashes - bench/compare.bench.ts > compiler_errors.ts
18.28x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > compiler_flags.ts
20.41x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > completions.ts
11.08x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > cuts_out_unnecessary_code.ts
9.72x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > errorsWithGenerics.ts
11.08x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > highlighting.ts
10.90x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > import_files.ts
6.62x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > importsModules.ts
6.06x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > multiFileErrors.ts
4.35x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > query.ts
13.15x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > arbitraryCommands.ts
10.98x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > crossExports.ts
6.16x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > cut_file_errors.ts
10.34x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > cut_files.ts
13.73x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > handlesJSON.ts
4.16x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > inlineHighlights.ts
13.28x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > large-cut.ts
10.23x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > lib.ts
12.57x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > multiLookups.ts
11.82x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > queriesWithSpaceBefore.ts
12.51x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > queryHandlesNoToken.ts
10.36x faster than @typescript/twoslash
twoslashes - bench/compare.bench.ts > twoliner.ts
6.58x faster than @typescript/twoslash
License
MIT License © Microsoft Corporation MIT License © 2023-PRESENT Anthony Fu