From 54cdf3a08b80f106c4fd1e123fedab4b31421532 Mon Sep 17 00:00:00 2001 From: ejose19 <8742215+ejose19@users.noreply.github.com> Date: Sun, 18 Jul 2021 19:17:27 -0300 Subject: [PATCH] feat(repl): allow using "type" command on types/interfaces --- src/index.ts | 4 +++- src/repl.ts | 26 +++++++++++++++++++++++++- src/test/index.spec.ts | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index f770eceb3..23a3a04ca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -348,6 +348,7 @@ export interface TsConfigOptions export interface TypeInfo { name: string; comment: string; + kind?: _ts.ScriptElementKind; } /** @@ -831,8 +832,9 @@ export function create(rawOptions: CreateOptions = {}): Service { const info = service.getQuickInfoAtPosition(fileName, position); const name = ts.displayPartsToString(info ? info.displayParts : []); const comment = ts.displayPartsToString(info ? info.documentation : []); + const kind = info?.kind; - return { name, comment }; + return { name, comment, kind }; }; } else { const sys: _ts.System & _ts.FormatDiagnosticsHost = { diff --git a/src/repl.ts b/src/repl.ts index fca8b1bc6..cadf2a1ea 100644 --- a/src/repl.ts +++ b/src/repl.ts @@ -8,6 +8,7 @@ import { readFileSync, statSync } from 'fs'; import { Console } from 'console'; import type * as tty from 'tty'; import Module = require('module'); +import { ScriptElementKind } from 'typescript'; /** @internal */ export const EVAL_FILENAME = `[eval].ts`; @@ -306,7 +307,7 @@ function startRepl( } const undo = appendEval(state, identifier); - const { name, comment } = service.getTypeInfo( + let { name, comment, kind } = service.getTypeInfo( state.input, state.path, state.input.length @@ -314,6 +315,29 @@ function startRepl( undo(); + // Check if the user intended to query a Type/Interface + if (kind === '') { + // Workaround to get type information + const undo = appendEval(state, `1 as ${identifier}`); + const getTypeInfoRes = service.getTypeInfo( + state.input, + state.path, + state.input.length + ); + + undo(); + + if ( + [ + ScriptElementKind.typeElement, + ScriptElementKind.interfaceElement, + ].includes(getTypeInfoRes.kind!) + ) { + name = getTypeInfoRes.name; + comment = getTypeInfoRes.comment; + } + } + if (name) repl.outputStream.write(`${name}\n`); if (comment) repl.outputStream.write(`${comment}\n`); repl.displayPrompt(); diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts index c8c8a7e4b..b154efd6c 100644 --- a/src/test/index.spec.ts +++ b/src/test/index.spec.ts @@ -411,6 +411,25 @@ test.suite('ts-node', (test) => { ); }); + test('REPL "type" command can be used on types', async () => { + const execPromise = exec(`${cmd} --interactive`); + execPromise.child.stdin!.end( + 'type Foo = string | { x: 1 }\n' + + '.type Foo\n' + + 'interface Bar { x: string; y: number; }\n' + + '.type Bar' + ); + const { err, stdout } = await execPromise; + expect(err).to.equal(null); + expect(stdout).to.equal( + '> undefined\n' + + '> type Foo = string | {\n x: 1;\n}\n' + + '> undefined\n' + + '> interface Bar\n' + + '> ' + ); + }); + function createReplViaApi() { const stdin = new PassThrough(); const stdout = new PassThrough(); @@ -1654,6 +1673,7 @@ test.suite('ts-node', (test) => { service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 21) ).to.deep.equal({ comment: 'jsdoc here', + kind: 'const', name: 'const x: 10', }); }); @@ -1664,6 +1684,7 @@ test.suite('ts-node', (test) => { service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 0) ).to.deep.equal({ comment: '', + kind: undefined, name: '', }); });