or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-nodes.mdcode-generation.mdfile-system.mdindex.mdproject-management.mdtype-system.md

type-system.mddocs/

0

# Type System Integration

1

2

Direct access to TypeScript's type checker and type information for advanced static analysis and type-aware transformations. This enables sophisticated analysis of TypeScript code beyond syntax-level operations.

3

4

## Capabilities

5

6

### Type Checker

7

8

The TypeScript type checker provides comprehensive type analysis capabilities.

9

10

```typescript { .api }

11

class TypeChecker {

12

/** Get the type of a node at its location */

13

getTypeAtLocation(node: Node): Type;

14

15

/** Get the symbol at a specific location */

16

getSymbolAtLocation(node: Node): Symbol | undefined;

17

18

/** Get the type of a symbol at a specific location */

19

getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;

20

21

/** Get the apparent type (after applying type arguments) */

22

getApparentType(type: Type): Type;

23

24

/** Get the base type of a type */

25

getBaseTypeOfLiteralType(type: Type): Type;

26

27

/** Get the full type of a node (including contextual type) */

28

getFullTypeAtLocation(node: Node): Type;

29

30

/** Get the contextual type for an expression */

31

getContextualType(node: Expression): Type | undefined;

32

33

/** Get the signature from a declaration */

34

getSignatureFromDeclaration(node: SignatureDeclaration): Signature | undefined;

35

36

/** Get all signatures for a type */

37

getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];

38

39

/** Get the return type of a signature */

40

getReturnTypeOfSignature(signature: Signature): Type;

41

42

/** Check if types are assignable */

43

isTypeAssignableTo(source: Type, target: Type): boolean;

44

45

/** Get exports of a module */

46

getExportsOfModule(moduleSymbol: Symbol): Symbol[];

47

48

/** Get properties of a type */

49

getPropertiesOfType(type: Type): Symbol[];

50

51

/** Get all accessible symbols at location */

52

getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];

53

}

54

55

enum SignatureKind {

56

Call = 0,

57

Construct = 1,

58

}

59

```

60

61

### Type Class

62

63

Represents a TypeScript type with comprehensive type information and analysis methods.

64

65

```typescript { .api }

66

class Type {

67

/** Get the string representation of the type */

68

getText(enclosingNode?: Node, typeFormatFlags?: TypeFormatFlags): string;

69

70

/** Get the symbol associated with this type */

71

getSymbol(): Symbol | undefined;

72

73

/** Get the apparent type (after type argument substitution) */

74

getApparentType(): Type;

75

76

/** Get constraint of a type parameter */

77

getConstraint(): Type | undefined;

78

79

/** Get default type of a type parameter */

80

getDefault(): Type | undefined;

81

82

/** Get union types if this is a union type */

83

getUnionTypes(): Type[];

84

85

/** Get intersection types if this is an intersection type */

86

getIntersectionTypes(): Type[];

87

88

/** Get type arguments if this is a generic type instance */

89

getTypeArguments(): Type[];

90

91

/** Get call signatures */

92

getCallSignatures(): Signature[];

93

94

/** Get construct signatures */

95

getConstructSignatures(): Signature[];

96

97

/** Get array element type if this is an array type */

98

getArrayElementType(): Type | undefined;

99

100

/** Get number index type */

101

getNumberIndexType(): Type | undefined;

102

103

/** Get string index type */

104

getStringIndexType(): Type | undefined;

105

106

/** Get base types */

107

getBaseTypes(): Type[];

108

109

/** Check if this is an array type */

110

isArray(): boolean;

111

112

/** Check if this is a boolean type */

113

isBoolean(): boolean;

114

115

/** Check if this is a string type */

116

isString(): boolean;

117

118

/** Check if this is a number type */

119

isNumber(): boolean;

120

121

/** Check if this is a literal type */

122

isLiteral(): boolean;

123

124

/** Check if this is a boolean literal type */

125

isBooleanLiteral(): boolean;

126

127

/** Check if this is an enum literal type */

128

isEnumLiteral(): boolean;

129

130

/** Check if this is a number literal type */

131

isNumberLiteral(): boolean;

132

133

/** Check if this is a string literal type */

134

isStringLiteral(): boolean;

135

136

/** Check if this is a class type */

137

isClass(): boolean;

138

139

/** Check if this is a class or interface type */

140

isClassOrInterface(): boolean;

141

142

/** Check if this is an enum type */

143

isEnum(): boolean;

144

145

/** Check if this is an interface type */

146

isInterface(): boolean;

147

148

/** Check if this is an object type */

149

isObject(): boolean;

150

151

/** Check if this is a type parameter */

152

isTypeParameter(): boolean;

153

154

/** Check if this is a union type */

155

isUnion(): boolean;

156

157

/** Check if this is an intersection type */

158

isIntersection(): boolean;

159

160

/** Check if this is an anonymous type */

161

isAnonymous(): boolean;

162

163

/** Check if this is null */

164

isNull(): boolean;

165

166

/** Check if this is undefined */

167

isUndefined(): boolean;

168

169

/** Check if this is never */

170

isNever(): boolean;

171

172

/** Check if this is unknown */

173

isUnknown(): boolean;

174

175

/** Check if this is any */

176

isAny(): boolean;

177

178

/** Get literal value for literal types */

179

getLiteralValue(): string | number | boolean | undefined;

180

181

/** Get properties of this type */

182

getProperties(): Symbol[];

183

184

/** Get property by name */

185

getProperty(name: string): Symbol | undefined;

186

187

/** Get non-nullable type (removes null and undefined) */

188

getNonNullableType(): Type;

189

}

190

```

191

192

### Symbol Class

193

194

Represents a TypeScript symbol with name, declarations, and type information.

195

196

```typescript { .api }

197

class Symbol {

198

/** Get the symbol name */

199

getName(): string;

200

201

/** Get the escaped name */

202

getEscapedName(): string;

203

204

/** Get all declarations of this symbol */

205

getDeclarations(): Node[];

206

207

/** Get first declaration */

208

getFirstDeclaration(): Node | undefined;

209

210

/** Get value declaration (for symbols that have values) */

211

getValueDeclaration(): Node | undefined;

212

213

/** Get type declaration (for type symbols) */

214

getTypeDeclaration(): Node | undefined;

215

216

/** Get the symbol flags */

217

getFlags(): SymbolFlags;

218

219

/** Get exports if this is a module or namespace */

220

getExports(): Symbol[];

221

222

/** Get global exports */

223

getGlobalExports(): Symbol[];

224

225

/** Get members if this is a class or interface */

226

getMembers(): Symbol[];

227

228

/** Get the type of this symbol */

229

getTypeAtLocation(location: Node): Type;

230

231

/** Get documentation comment */

232

getDocumentationComment(): SymbolDisplayPart[];

233

234

/** Get JSDoc tags */

235

getJsDocTags(): JSDocTagInfo[];

236

237

/** Check if symbol has specific flag */

238

hasFlag(flag: SymbolFlags): boolean;

239

240

/** Check if symbol is optional */

241

isOptional(): boolean;

242

}

243

```

244

245

### Signature Class

246

247

Represents a function or method signature with parameter and return type information.

248

249

```typescript { .api }

250

class Signature {

251

/** Get parameters of this signature */

252

getParameters(): Symbol[];

253

254

/** Get return type */

255

getReturnType(): Type;

256

257

/** Get type parameters */

258

getTypeParameters(): TypeParameter[];

259

260

/** Get the declaration associated with this signature */

261

getDeclaration(): SignatureDeclaration | undefined;

262

263

/** Get documentation comment */

264

getDocumentationComment(): SymbolDisplayPart[];

265

266

/** Get JSDoc tags */

267

getJsDocTags(): JSDocTagInfo[];

268

269

/** Get signature string representation */

270

getText(): string;

271

}

272

273

class TypeParameter extends Type {

274

/** Get the constraint of this type parameter */

275

getConstraint(): Type | undefined;

276

277

/** Get the default type of this type parameter */

278

getDefault(): Type | undefined;

279

}

280

```

281

282

### Diagnostic Information

283

284

TypeScript diagnostic information for errors, warnings, and suggestions.

285

286

```typescript { .api }

287

class Diagnostic {

288

/** Get the diagnostic message text */

289

getMessageText(): string;

290

291

/** Get the source file where this diagnostic occurred */

292

getSourceFile(): SourceFile | undefined;

293

294

/** Get the start position */

295

getStart(): number | undefined;

296

297

/** Get the length */

298

getLength(): number | undefined;

299

300

/** Get the end position */

301

getEnd(): number | undefined;

302

303

/** Get diagnostic category */

304

getCategory(): DiagnosticCategory;

305

306

/** Get diagnostic code */

307

getCode(): number;

308

309

/** Get the line number (1-indexed) */

310

getLineNumber(): number | undefined;

311

}

312

313

interface SymbolDisplayPart {

314

text: string;

315

kind: string;

316

}

317

318

interface JSDocTagInfo {

319

name: string;

320

text?: SymbolDisplayPart[];

321

}

322

```

323

324

### Language Service

325

326

TypeScript language service providing IDE-like functionality.

327

328

```typescript { .api }

329

class LanguageService {

330

/** Get completions at a position */

331

getCompletionsAtPosition(fileName: string, position: number): CompletionInfo | undefined;

332

333

/** Get quick info at a position */

334

getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined;

335

336

/** Get definition at a position */

337

getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];

338

339

/** Get type definition at a position */

340

getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];

341

342

/** Get references at a position */

343

getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];

344

345

/** Get semantic diagnostics */

346

getSemanticDiagnostics(fileName: string): Diagnostic[];

347

348

/** Get syntactic diagnostics */

349

getSyntacticDiagnostics(fileName: string): Diagnostic[];

350

351

/** Get suggestion diagnostics */

352

getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[];

353

354

/** Find all references */

355

findReferences(fileName: string, position: number): ReferencedSymbol[];

356

357

/** Get rename info */

358

getRenameInfo(fileName: string, position: number): RenameInfo;

359

360

/** Find rename locations */

361

findRenameLocations(fileName: string, position: number, findInStrings?: boolean, findInComments?: boolean): RenameLocation[];

362

}

363

364

interface CompletionInfo {

365

entries: CompletionEntry[];

366

isGlobalCompletion: boolean;

367

isMemberCompletion: boolean;

368

isNewIdentifierLocation: boolean;

369

}

370

371

interface CompletionEntry {

372

name: string;

373

kind: string;

374

kindModifiers?: string;

375

sortText: string;

376

insertText?: string;

377

replacementSpan?: TextSpan;

378

}

379

380

interface QuickInfo {

381

kind: string;

382

kindModifiers: string;

383

textSpan: TextSpan;

384

displayParts?: SymbolDisplayPart[];

385

documentation?: SymbolDisplayPart[];

386

tags?: JSDocTagInfo[];

387

}

388

389

interface DefinitionInfo {

390

fileName: string;

391

textSpan: TextSpan;

392

kind: string;

393

name: string;

394

containerKind: string;

395

containerName: string;

396

}

397

398

interface TextSpan {

399

start: number;

400

length: number;

401

}

402

```

403

404

**Usage Examples:**

405

406

```typescript

407

import { Project, SyntaxKind } from "ts-morph";

408

409

const project = new Project({

410

tsConfigFilePath: "tsconfig.json",

411

});

412

413

const sourceFile = project.createSourceFile("analysis.ts", `

414

interface User {

415

id: number;

416

name: string;

417

email?: string;

418

}

419

420

class UserService {

421

private users: User[] = [];

422

423

async getUser(id: number): Promise<User | undefined> {

424

return this.users.find(user => user.id === id);

425

}

426

}

427

428

const service = new UserService();

429

const user = service.getUser(1);

430

`);

431

432

const typeChecker = project.getTypeChecker();

433

434

// Analyze types

435

const userInterface = sourceFile.getInterfaceOrThrow("User");

436

const userType = typeChecker.getTypeAtLocation(userInterface);

437

438

console.log("User type text:", userType.getText());

439

console.log("Is User an object type:", userType.isObject());

440

441

// Get properties of User interface

442

const properties = userType.getProperties();

443

properties.forEach(prop => {

444

const propType = typeChecker.getTypeOfSymbolAtLocation(prop, userInterface);

445

console.log(\`Property \${prop.getName()}: \${propType.getText()}\`);

446

console.log(\`Is optional: \${prop.isOptional()}\`);

447

});

448

449

// Analyze method return types

450

const userServiceClass = sourceFile.getClassOrThrow("UserService");

451

const getUserMethod = userServiceClass.getMethodOrThrow("getUser");

452

const signature = typeChecker.getSignatureFromDeclaration(getUserMethod);

453

454

if (signature) {

455

const returnType = signature.getReturnType();

456

console.log("getUser return type:", returnType.getText());

457

console.log("Is Promise:", returnType.getText().startsWith("Promise"));

458

459

// Get the actual type inside Promise

460

const typeArgs = returnType.getTypeArguments();

461

if (typeArgs.length > 0) {

462

console.log("Promise type argument:", typeArgs[0].getText());

463

}

464

}

465

466

// Analyze variable types

467

const serviceVariable = sourceFile.getVariableDeclarationOrThrow("service");

468

const serviceType = typeChecker.getTypeAtLocation(serviceVariable);

469

console.log("Service variable type:", serviceType.getText());

470

471

// Find all number literal types

472

const numberLiterals = sourceFile.getDescendantsOfKind(SyntaxKind.NumericLiteral);

473

numberLiterals.forEach(literal => {

474

const type = typeChecker.getTypeAtLocation(literal);

475

console.log(\`Number literal \${literal.getText()} has type: \${type.getText()}\`);

476

console.log("Is number literal type:", type.isNumberLiteral());

477

if (type.isNumberLiteral()) {

478

console.log("Literal value:", type.getLiteralValue());

479

}

480

});

481

482

// Check type assignability

483

const numberType = typeChecker.getTypeAtLocation(

484

sourceFile.getFirstDescendantByKindOrThrow(SyntaxKind.NumericLiteral)

485

);

486

const stringType = typeChecker.getTypeAtLocation(

487

sourceFile.addVariableStatement({

488

declarationKind: "const",

489

declarations: [{ name: "temp", initializer: "'hello'" }]

490

}).getDeclarations()[0]

491

);

492

493

console.log("Can assign string to number:",

494

typeChecker.isTypeAssignableTo(stringType, numberType));

495

```

496

497

**Advanced Type Analysis:**

498

499

```typescript

500

import { Project } from "ts-morph";

501

502

const project = new Project();

503

const sourceFile = project.createSourceFile("advanced.ts", `

504

type EventHandler<T> = (event: T) => void;

505

506

interface ClickEvent {

507

type: 'click';

508

x: number;

509

y: number;

510

}

511

512

interface KeyEvent {

513

type: 'key';

514

key: string;

515

code: number;

516

}

517

518

type AllEvents = ClickEvent | KeyEvent;

519

520

class EventEmitter {

521

private handlers: Map<string, EventHandler<any>[]> = new Map();

522

523

on<T extends AllEvents>(type: T['type'], handler: EventHandler<T>): void {

524

// Implementation

525

}

526

}

527

`);

528

529

const typeChecker = project.getTypeChecker();

530

531

// Analyze generic types

532

const eventHandlerType = sourceFile.getTypeAliasOrThrow("EventHandler");

533

const handlerType = typeChecker.getTypeAtLocation(eventHandlerType);

534

535

console.log("EventHandler type:", handlerType.getText());

536

537

// Analyze union types

538

const allEventsType = sourceFile.getTypeAliasOrThrow("AllEvents");

539

const unionType = typeChecker.getTypeAtLocation(allEventsType);

540

541

console.log("AllEvents is union:", unionType.isUnion());

542

if (unionType.isUnion()) {

543

const unionTypes = unionType.getUnionTypes();

544

unionTypes.forEach((type, index) => {

545

console.log(\`Union member \${index}: \${type.getText()}\`);

546

547

// Analyze each union member's properties

548

const properties = type.getProperties();

549

properties.forEach(prop => {

550

const propType = typeChecker.getTypeOfSymbolAtLocation(prop, allEventsType);

551

console.log(\` Property \${prop.getName()}: \${propType.getText()}\`);

552

});

553

});

554

}

555

556

// Analyze generic method constraints

557

const eventEmitterClass = sourceFile.getClassOrThrow("EventEmitter");

558

const onMethod = eventEmitterClass.getMethodOrThrow("on");

559

const onSignature = typeChecker.getSignatureFromDeclaration(onMethod);

560

561

if (onSignature) {

562

const typeParams = onSignature.getTypeParameters();

563

typeParams.forEach(typeParam => {

564

console.log("Type parameter:", typeParam.getText());

565

const constraint = typeParam.getConstraint();

566

if (constraint) {

567

console.log("Constraint:", constraint.getText());

568

}

569

});

570

}

571

```