This page covers two related language service subsystems: the inlay hints service, which computes inline type and parameter annotations shown in editors, and the symbol display utilities, which convert TypeScript symbols and types into structured text representations used for hover tooltips, completions, and similar UI features.
For the language service API that hosts these subsystems, see Language Service. For completions (which also uses symbol display), see Code Completions. For signature help, see Signature Help.
Inlay hints are editor decorations that appear inline in source code to reveal inferred information that is not explicitly written. TypeScript's inlay hints service produces five distinct categories of hints, all computed on demand over a specific TextSpan within a SourceFile.
| Hint Category | Preference Flag | Example |
|---|---|---|
| Parameter names at call sites | includeInlayParameterNameHints | foo(/*value:*/ 42) |
| Variable / property inferred types | includeInlayVariableTypeHints / includeInlayPropertyDeclarationTypeHints | const x/*: string*/ = ... |
| Function / method return types | includeInlayFunctionLikeReturnTypeHints | function f()/*: void*/ {} |
| Untyped function parameter types | includeInlayFunctionParameterTypeHints | (a/*: string*/) => {} |
| Enum member computed values | includeInlayEnumMemberValueHints | A /*= 0*/ |
The public entry point is provideInlayHints in src/services/inlayHints.ts148-158
provideInlayHints(context: InlayHintsContext): InlayHint[]
InlayHintsContext carries everything the function needs:
| Field | Type | Purpose |
|---|---|---|
file | SourceFile | The file being analyzed |
program | Program | The full compilation for type-checker access |
span | TextSpan | The range of text to emit hints for |
cancellationToken | CancellationToken | For cooperative cancellation |
preferences | UserPreferences | Flags that control which hints are produced |
The function acquires a TypeChecker from program.getTypeChecker() and immediately starts a recursive visitor walk over the AST, filtering nodes to those that intersect span.
Sources: src/services/inlayHints.ts148-206
InlayHint is the output unit:
| Field | Type | Notes |
|---|---|---|
text | string | Plain-text label; empty when displayParts is used |
position | number | Insertion offset in source text |
kind | InlayHintKind | Parameter, Type, or Enum |
whitespaceBefore | boolean? | Add a space before the hint |
whitespaceAfter | boolean? | Add a space after the hint |
displayParts | InlayHintDisplayPart[]? | Structured parts for interactive mode |
InlayHintDisplayPart (used in interactive mode):
| Field | Type | Notes |
|---|---|---|
text | string | The text fragment |
span | TextSpan? | Source range for go-to-definition navigation |
file | string? | Source file for span |
Sources: src/services/inlayHints.ts33-36 src/services/inlayHints.ts212-249
The visitor function applies per-node logic depending on UserPreferences flags:
Inlay hints visitor dispatch
Sources: src/services/inlayHints.ts160-206
Handled by visitCallOrNewExpression src/services/inlayHints.ts295-345
Signature via checker.getResolvedSignature(expr).ParameterIdentifierInfo via checker.getParameterIdentifierInfoAtPosition(signature, pos).isHintableLiteral).identifierOrAccessExpressionPostfixMatchesParameterName)./* paramName */ comment is already present (leadingCommentsContainsParameterName).addParameterHints(name, parameter, position, isFirstVariadicArgument).The leadingParameterNameCommentRegexFactory src/services/inlayHints.ts131-133 builds a regex that matches /* name */ patterns to detect manual inline annotations.
Variable and property type hints — visitVariableLikeDeclaration src/services/inlayHints.ts266-293:
getEffectiveTypeAnnotationNode).includeInlayVariableTypeHintsWhenTypeMatchesName === false and the variable name matches the type name (case-insensitive).Return type hints — visitFunctionDeclarationLikeForReturnType src/services/inlayHints.ts391-427:
FunctionDeclaration, ArrowFunction, FunctionExpression, MethodDeclaration, GetAccessorDeclaration.getEffectiveReturnTypeNode already exists or the function has no body.checker.getTypePredicateOfSignature when available.checker.getReturnTypeOfSignature.getTypeAnnotationPosition, which is the position after the close-paren token.Contextual parameter type hints — visitFunctionLikeForParameterType src/services/inlayHints.ts437-453:
hasContextSensitiveParameters(node) is true — i.e. the function has unannotated parameters whose types are determined by contextual typing.visitEnumMember src/services/inlayHints.ts251-260 skips members that already have an initializer and uses checker.getConstantValue(member) to get the computed value, producing a hint like = 0 at member.end.
When preferences.interactiveInlayHints === true, type hints carry structured InlayHintDisplayPart[] instead of plain text. This allows editors to embed navigation links (go-to-definition) directly in hints.
Type serialization pipeline
printTypeInSingleLine src/services/inlayHints.ts478-487 uses createPrinterWithRemoveComments and usingSingleLineStringWriter to emit a single-line type string.
getInlayHintDisplayParts src/services/inlayHints.ts522-526 recursively walks the type node (visitForDisplayParts) and produces parts. Named identifier nodes get a span field pointing to the declaration in the source, enabling editor navigation. The logic handles all major type node kinds including TypeReference, UnionType, IntersectionType, ConditionalType, MappedType, FunctionType, TupleType, ImportType, and more.
Flags used during type node construction:
NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.AllowUniqueESSymbolType | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope
Sources: src/services/inlayHints.ts478-519 src/services/inlayHints.ts522-900
The symbol display subsystem in src/services/symbolDisplay.ts converts TypeScript Symbol and Type objects into arrays of SymbolDisplayPart values — tagged text fragments that editors render as formatted hover tooltips, completion detail text, and similar surfaces.
The primary output structure is SymbolDisplayPartsDocumentationAndSymbolKind:
interface SymbolDisplayPartsDocumentationAndSymbolKind {
displayParts: SymbolDisplayPart[]; // formatted signature/type text
documentation: SymbolDisplayPart[]; // JSDoc comment text
symbolKind: ScriptElementKind; // e.g. "function", "class", "const"
tags: JSDocTagInfo[] | undefined; // JSDoc @tags
canIncreaseVerbosityLevel?: boolean; // whether more detail is available
}
Sources: src/services/symbolDisplay.ts252-259
getSymbolKind src/services/symbolDisplay.ts118-138 maps a Symbol to a ScriptElementKind string, used by completions, hover, and navigation to classify entries.
The inner function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar src/services/symbolDisplay.ts140-214 handles fine-grained disambiguation:
| SymbolFlags | ScriptElementKind |
|---|---|
Variable (is parameter) | parameterElement |
Variable (const) | constElement |
Variable (let) | letElement |
Variable (using) | variableUsingElement |
Variable (await using) | variableAwaitUsingElement |
Function (local) | localFunctionElement |
Function | functionElement |
GetAccessor | memberGetAccessorElement |
SetAccessor | memberSetAccessorElement |
Method | memberFunctionElement |
Constructor | constructorImplementationElement |
Property (with call sigs) | memberFunctionElement |
Property | memberVariableElement |
Class | classElement / localClassElement |
Enum | enumElement |
TypeAlias | typeElement |
Interface | interfaceElement |
TypeParameter | typeParameterElement |
EnumMember | enumMemberElement |
Alias | alias |
Module | moduleElement |
Sources: src/services/symbolDisplay.ts118-214
getSymbolModifiers src/services/symbolDisplay.ts232-250 builds a comma-separated modifier string from a symbol's declarations (e.g. "abstract,deprecated,optional").
getNodeModifiers.SymbolFlags.Alias.ScriptElementKindModifier.optionalModifier when SymbolFlags.Optional is set.ModifierFlags.Deprecated from the set if only some declarations are deprecated.Sources: src/services/symbolDisplay.ts216-250
The core function is getSymbolDisplayPartsDocumentationAndSymbolKindWorker src/services/symbolDisplay.ts261-800 which builds the displayParts array by examining the symbol's flags, the call context, and the location node.
Display parts assembly flow
Sources: src/services/symbolDisplay.ts261-800
SymbolDisplayPart has the shape { text: string, kind: string } where kind is the string name of a SymbolDisplayPartKind enum value.
| Kind | Example Text |
|---|---|
aliasName | an import/export alias name |
className | MyClass |
enumName | Direction |
fieldName | myProp |
interfaceName | Iterable |
keyword | function, class, type |
lineBreak | newline between overloads |
numericLiteral | 42 |
operator | =, => |
parameterName | value |
propertyName | object key name |
punctuation | (, ), :, ; |
space | |
stringLiteral | "hello" |
text | misc text, e.g. "type parameter" |
typeParameterName | T |
moduleName | module name |
functionName | myFunc |
regularExpressionLiteral | regex text |
The helper constructors keywordPart, punctuationPart, operatorPart, spacePart, textPart, lineBreakPart from src/services/_namespaces/ts.js are used throughout symbolDisplay.ts to build the displayParts array.
Sources: src/services/symbolDisplay.ts69-112
Both subsystems rely on shared utilities from the type checker and printer:
| Utility | Location | Role |
|---|---|---|
typeToDisplayParts | services namespace | Converts Type → SymbolDisplayPart[] |
symbolToDisplayParts | services namespace | Converts Symbol → SymbolDisplayPart[] |
signatureToDisplayParts | services namespace | Converts Signature → SymbolDisplayPart[] |
mapToDisplayParts | services namespace | Wraps a writer callback to collect display parts |
checker.typeToTypeNode | TypeChecker | Converts Type → AST TypeNode |
checker.typePredicateToTypePredicateNode | TypeChecker | Converts TypePredicate → AST node |
createPrinterWithRemoveComments | compiler | Printer for single-line type text |
usingSingleLineStringWriter | compiler | String writer utility |
The symbolDisplayNodeBuilderFlags constant used in symbolDisplay.ts is:
NodeBuilderFlags.OmitParameterModifiers
| NodeBuilderFlags.IgnoreErrors
| NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope
Sources: src/services/symbolDisplay.ts114 src/services/inlayHints.ts479-480
All inlay hint behavior is gated by UserPreferences fields:
| Preference | Type | Effect |
|---|---|---|
includeInlayParameterNameHints | "none" | "literals" | "all" | Controls parameter name hints |
includeInlayParameterNameHintsWhenArgumentMatchesName | boolean | Show hint even when arg name matches param |
includeInlayVariableTypeHints | boolean | Infer type hints for variables |
includeInlayVariableTypeHintsWhenTypeMatchesName | boolean | Show hint even when names match |
includeInlayPropertyDeclarationTypeHints | boolean | Infer type hints for class properties |
includeInlayFunctionParameterTypeHints | boolean | Show contextual param types in lambdas |
includeInlayFunctionLikeReturnTypeHints | boolean | Infer return type for functions |
includeInlayEnumMemberValueHints | boolean | Show computed enum values |
interactiveInlayHints | boolean | Use displayParts with navigation spans |
Sources: src/services/inlayHints.ts135-145
How inlay hints and symbol display fit into the language service
Sources: src/services/inlayHints.ts148-158 src/services/symbolDisplay.ts252-259
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.