diff --git a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-7.18.0-f1d556a934-6ee4c61f14.zip b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.0.0-1d851e884d-80c52b37f8.zip similarity index 56% rename from .yarn/cache/@typescript-eslint-eslint-plugin-npm-7.18.0-f1d556a934-6ee4c61f14.zip rename to .yarn/cache/@typescript-eslint-eslint-plugin-npm-8.0.0-1d851e884d-80c52b37f8.zip index e18aac106..df521e0fc 100644 Binary files a/.yarn/cache/@typescript-eslint-eslint-plugin-npm-7.18.0-f1d556a934-6ee4c61f14.zip and b/.yarn/cache/@typescript-eslint-eslint-plugin-npm-8.0.0-1d851e884d-80c52b37f8.zip differ diff --git a/.yarn/cache/@typescript-eslint-parser-npm-7.18.0-df2ed0084c-36b00e192a.zip b/.yarn/cache/@typescript-eslint-parser-npm-7.18.0-df2ed0084c-36b00e192a.zip deleted file mode 100644 index 6e4139607..000000000 Binary files a/.yarn/cache/@typescript-eslint-parser-npm-7.18.0-df2ed0084c-36b00e192a.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-parser-npm-8.0.0-271269d04b-044a7deb29.zip b/.yarn/cache/@typescript-eslint-parser-npm-8.0.0-271269d04b-044a7deb29.zip new file mode 100644 index 000000000..8694fccff Binary files /dev/null and b/.yarn/cache/@typescript-eslint-parser-npm-8.0.0-271269d04b-044a7deb29.zip differ diff --git a/.yarn/cache/@typescript-eslint-scope-manager-npm-7.18.0-c84582852c-9eb2ae5d69.zip b/.yarn/cache/@typescript-eslint-scope-manager-npm-8.0.0-7eded7f3f2-444dbc156d.zip similarity index 64% rename from .yarn/cache/@typescript-eslint-scope-manager-npm-7.18.0-c84582852c-9eb2ae5d69.zip rename to .yarn/cache/@typescript-eslint-scope-manager-npm-8.0.0-7eded7f3f2-444dbc156d.zip index 811faa99a..235572fc0 100644 Binary files a/.yarn/cache/@typescript-eslint-scope-manager-npm-7.18.0-c84582852c-9eb2ae5d69.zip and b/.yarn/cache/@typescript-eslint-scope-manager-npm-8.0.0-7eded7f3f2-444dbc156d.zip differ diff --git a/.yarn/cache/@typescript-eslint-type-utils-npm-7.18.0-acee9c858d-bcc7958a4e.zip b/.yarn/cache/@typescript-eslint-type-utils-npm-7.18.0-acee9c858d-bcc7958a4e.zip deleted file mode 100644 index ecba1dd31..000000000 Binary files a/.yarn/cache/@typescript-eslint-type-utils-npm-7.18.0-acee9c858d-bcc7958a4e.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-type-utils-npm-8.0.0-ed297ac445-89ca36511a.zip b/.yarn/cache/@typescript-eslint-type-utils-npm-8.0.0-ed297ac445-89ca36511a.zip new file mode 100644 index 000000000..4735bc295 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-type-utils-npm-8.0.0-ed297ac445-89ca36511a.zip differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-7.18.0-43e7278412-0e30c73a3c.zip b/.yarn/cache/@typescript-eslint-types-npm-7.18.0-43e7278412-0e30c73a3c.zip deleted file mode 100644 index 2ff634455..000000000 Binary files a/.yarn/cache/@typescript-eslint-types-npm-7.18.0-43e7278412-0e30c73a3c.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-types-npm-8.0.0-4d43d4dad8-e28e79d8b7.zip b/.yarn/cache/@typescript-eslint-types-npm-8.0.0-4d43d4dad8-e28e79d8b7.zip new file mode 100644 index 000000000..e18ca5415 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-types-npm-8.0.0-4d43d4dad8-e28e79d8b7.zip differ diff --git a/.yarn/cache/@typescript-eslint-typescript-estree-npm-7.18.0-ce673565ca-b01e66235a.zip b/.yarn/cache/@typescript-eslint-typescript-estree-npm-7.18.0-ce673565ca-b01e66235a.zip deleted file mode 100644 index e67ccb265..000000000 Binary files a/.yarn/cache/@typescript-eslint-typescript-estree-npm-7.18.0-ce673565ca-b01e66235a.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.0.0-7780851516-99a80fb43d.zip b/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.0.0-7780851516-99a80fb43d.zip new file mode 100644 index 000000000..88317a827 Binary files /dev/null and b/.yarn/cache/@typescript-eslint-typescript-estree-npm-8.0.0-7780851516-99a80fb43d.zip differ diff --git a/.yarn/cache/@typescript-eslint-utils-npm-7.18.0-d11315a14c-f43fedb4f4.zip b/.yarn/cache/@typescript-eslint-utils-npm-8.0.0-01d19a1298-f76e657637.zip similarity index 54% rename from .yarn/cache/@typescript-eslint-utils-npm-7.18.0-d11315a14c-f43fedb4f4.zip rename to .yarn/cache/@typescript-eslint-utils-npm-8.0.0-01d19a1298-f76e657637.zip index e28f1b8d3..775a1640f 100644 Binary files a/.yarn/cache/@typescript-eslint-utils-npm-7.18.0-d11315a14c-f43fedb4f4.zip and b/.yarn/cache/@typescript-eslint-utils-npm-8.0.0-01d19a1298-f76e657637.zip differ diff --git a/.yarn/cache/@typescript-eslint-visitor-keys-npm-7.18.0-8b4d3089ad-b7cfe6fdea.zip b/.yarn/cache/@typescript-eslint-visitor-keys-npm-7.18.0-8b4d3089ad-b7cfe6fdea.zip deleted file mode 100644 index a0d4fc508..000000000 Binary files a/.yarn/cache/@typescript-eslint-visitor-keys-npm-7.18.0-8b4d3089ad-b7cfe6fdea.zip and /dev/null differ diff --git a/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.0.0-bf14db79d7-328106878e.zip b/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.0.0-bf14db79d7-328106878e.zip new file mode 100644 index 000000000..3429a338b Binary files /dev/null and b/.yarn/cache/@typescript-eslint-visitor-keys-npm-8.0.0-bf14db79d7-328106878e.zip differ diff --git a/.yarn/cache/typescript-eslint-npm-7.18.0-9c7ae1056a-7c1ad00ecd.zip b/.yarn/cache/typescript-eslint-npm-7.18.0-9c7ae1056a-7c1ad00ecd.zip deleted file mode 100644 index 4dcc529de..000000000 Binary files a/.yarn/cache/typescript-eslint-npm-7.18.0-9c7ae1056a-7c1ad00ecd.zip and /dev/null differ diff --git a/.yarn/cache/typescript-eslint-npm-8.0.0-b15bb48034-128c1ff75d.zip b/.yarn/cache/typescript-eslint-npm-8.0.0-b15bb48034-128c1ff75d.zip new file mode 100644 index 000000000..e161a0e8e Binary files /dev/null and b/.yarn/cache/typescript-eslint-npm-8.0.0-b15bb48034-128c1ff75d.zip differ diff --git a/eslint.config.js b/eslint.config.js index c6bf3d0b6..5b5873ed2 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -41,7 +41,17 @@ export default tseslint.config( }, { files: ['**/*.mts', '**/*.ts'], - extends: [...tseslint.configs.recommended], + extends: [...tseslint.configs.recommendedTypeChecked], + languageOptions: { + parserOptions: { + projectService: { + allowDefaultProject: ['packages/*/*.test.mts'], + defaultProject: './tsconfig.test.json', + maximumDefaultProjectFileMatchCount_THIS_WILL_SLOW_DOWN_LINTING: 20, + }, + tsconfigRootDir: import.meta.dirname, + }, + }, }, { files: ['**/*.cjs'], @@ -55,6 +65,7 @@ export default tseslint.config( { files: ['packages/inquirer/test/**', 'packages/**/*.test.*'], rules: { + '@typescript-eslint/unbound-method': 'off', 'n/no-extraneous-import': [ 'error', { diff --git a/package.json b/package.json index ab6ad147f..83da98d2e 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "ts-node": "^10.9.2", "turbo": "^2.0.11", "typescript": "^5.5.4", - "typescript-eslint": "^7.18.0", + "typescript-eslint": "^8.0.0", "vitest": "^2.0.5" }, "resolutions": { diff --git a/packages/checkbox/src/index.mts b/packages/checkbox/src/index.mts index 3d7d8f099..a8339782c 100644 --- a/packages/checkbox/src/index.mts +++ b/packages/checkbox/src/index.mts @@ -186,7 +186,7 @@ export default createPrompt( return ` ${item.separator}`; } - const line = item.name || item.value; + const line = String(item.name || item.value); if (item.disabled) { const disabledLabel = typeof item.disabled === 'string' ? item.disabled : '(disabled)'; diff --git a/packages/core/core.test.mts b/packages/core/core.test.mts index 69fa2f88a..56b787550 100644 --- a/packages/core/core.test.mts +++ b/packages/core/core.test.mts @@ -579,6 +579,7 @@ describe('Error handling', () => { it('prevent returning promises from useEffect hook', async () => { const Prompt = (_config: object, done: (value: string) => void) => { // @ts-expect-error: Testing an invalid behavior. + // eslint-disable-next-line @typescript-eslint/require-await useEffect(async () => { done('done'); }, []); @@ -595,7 +596,7 @@ describe('Error handling', () => { await expect(answer).rejects.toBeInstanceOf(ValidationError); }); - it('useEffect throws outside prompt', async () => { + it('useEffect throws outside prompt', () => { expect(() => { useEffect(() => {}, []); }).toThrowErrorMatchingInlineSnapshot( @@ -606,7 +607,7 @@ describe('Error handling', () => { }).toThrow(HookError); }); - it('useKeypress throws outside prompt', async () => { + it('useKeypress throws outside prompt', () => { expect(() => { useKeypress(() => {}); }).toThrowErrorMatchingInlineSnapshot( diff --git a/packages/core/src/lib/pagination/lines.test.mts b/packages/core/lines.test.mts similarity index 98% rename from packages/core/src/lib/pagination/lines.test.mts rename to packages/core/lines.test.mts index 1c811f10f..50190a57d 100644 --- a/packages/core/src/lib/pagination/lines.test.mts +++ b/packages/core/lines.test.mts @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { lines } from './lines.mjs'; +import { lines } from './src/lib/pagination/lines.mjs'; function renderResult(result: string[]) { return `\n${result.join('\n')}\n`; diff --git a/packages/core/src/lib/hook-engine.mts b/packages/core/src/lib/hook-engine.mts index 3d5837a95..ff23942d3 100644 --- a/packages/core/src/lib/hook-engine.mts +++ b/packages/core/src/lib/hook-engine.mts @@ -63,10 +63,10 @@ export function readline(): InquirerReadline { } // Merge state updates happening within the callback function to avoid multiple renders. -export function withUpdates any>( +export function withUpdates R>( fn: T, -): (...args: Parameters) => ReturnType { - const wrapped = (...args: any): ReturnType => { +): (...args: Parameters) => R { + const wrapped = (...args: Parameters): R => { const store = getStore(); let shouldUpdate = false; const oldHandleChange = store.handleChange; @@ -105,10 +105,10 @@ export function withPointer( const { index } = store; const pointer: Pointer = { - get() { + get(): any { return store.hooks[index]; }, - set(value: any) { + set(value: unknown) { store.hooks[index] = value; }, initialized: index in store.hooks, diff --git a/packages/core/src/lib/make-theme.mts b/packages/core/src/lib/make-theme.mts index 3b5819e9b..290fe2f0d 100644 --- a/packages/core/src/lib/make-theme.mts +++ b/packages/core/src/lib/make-theme.mts @@ -4,7 +4,7 @@ import { defaultTheme, type Theme } from './theme.mjs'; function isPlainObject(value: unknown): value is object { if (typeof value !== 'object' || value === null) return false; - let proto = value; + let proto: unknown = value; while (Object.getPrototypeOf(proto) !== null) { proto = Object.getPrototypeOf(proto); } diff --git a/packages/core/src/lib/use-keypress.mts b/packages/core/src/lib/use-keypress.mts index 7a4589ba9..57f5ffa7e 100644 --- a/packages/core/src/lib/use-keypress.mts +++ b/packages/core/src/lib/use-keypress.mts @@ -5,7 +5,7 @@ import { useEffect } from './use-effect.mjs'; import { withUpdates } from './hook-engine.mjs'; export function useKeypress( - userHandler: (event: KeypressEvent, rl: InquirerReadline) => void, + userHandler: (event: KeypressEvent, rl: InquirerReadline) => void | Promise, ) { const signal = useRef(userHandler); signal.current = userHandler; @@ -14,7 +14,7 @@ export function useKeypress( let ignore = false; const handler = withUpdates((_input: string, event: KeypressEvent) => { if (ignore) return; - signal.current(event, rl); + void signal.current(event, rl); }); rl.input.on('keypress', handler); diff --git a/packages/core/src/lib/use-state.mts b/packages/core/src/lib/use-state.mts index 47cc6e130..639758b10 100644 --- a/packages/core/src/lib/use-state.mts +++ b/packages/core/src/lib/use-state.mts @@ -1,7 +1,6 @@ import { withPointer, handleChange } from './hook-engine.mjs'; -// eslint-disable-next-line @typescript-eslint/ban-types -type NotFunction = T extends Function ? never : T; +type NotFunction = T extends (...args: never) => unknown ? never : T; export function useState( defaultValue: NotFunction | (() => Value), diff --git a/packages/editor/editor.test.mts b/packages/editor/editor.test.mts index defb74327..eb111b5f9 100644 --- a/packages/editor/editor.test.mts +++ b/packages/editor/editor.test.mts @@ -13,7 +13,10 @@ async function editorAction(error: undefined | Error, value?: string) { if (!lastCall) throw new Error("editor wasn't open"); // Bugfix: The callback error value is nullable. - const editCallback = lastCall[1] as (error: undefined | Error, value: string) => void; + const editCallback = lastCall[1] as ( + error: undefined | Error, + value: string, + ) => void | Promise; await editCallback(error, value ?? ''); } diff --git a/packages/editor/src/index.mts b/packages/editor/src/index.mts index 3389cdb41..055273cbf 100644 --- a/packages/editor/src/index.mts +++ b/packages/editor/src/index.mts @@ -22,7 +22,7 @@ type EditorConfig = { }; export default createPrompt((config, done) => { - const { waitForUseInput = true, validate = () => true } = config; + const { waitForUseInput = true, postfix = '.txt', validate = () => true } = config; const theme = makeTheme(config.theme); const [status, setStatus] = useState('pending'); @@ -34,31 +34,28 @@ export default createPrompt((config, done) => { function startEditor(rl: InquirerReadline) { rl.pause(); - editAsync( - value, - // Note: The bind call isn't strictly required. But we need it for our mocks to work as expected. - AsyncResource.bind(async (error, answer) => { - rl.resume(); - if (error) { - setError(error.toString()); + + // Note: The bind call isn't strictly required. But we need it for our mocks to work as expected. + const editCallback = AsyncResource.bind(async (error: Error, answer: string) => { + rl.resume(); + if (error) { + setError(error.toString()); + } else { + setStatus('loading'); + const isValid = await validate(answer); + if (isValid === true) { + setError(undefined); + setStatus('done'); + done(answer); } else { - setStatus('loading'); - const isValid = await validate(answer); - if (isValid === true) { - setError(undefined); - setStatus('done'); - done(answer); - } else { - setValue(answer); - setError(isValid || 'You must provide a valid value'); - setStatus('pending'); - } + setValue(answer); + setError(isValid || 'You must provide a valid value'); + setStatus('pending'); } - }), - { - postfix: config.postfix || '.txt', - }, - ); + } + }); + + editAsync(value, (error, answer) => void editCallback(error, answer), { postfix }); } useEffect((rl) => { diff --git a/packages/inquirer/test/inquirer.test.mts b/packages/inquirer/inquirer.test.mts similarity index 96% rename from packages/inquirer/test/inquirer.test.mts rename to packages/inquirer/inquirer.test.mts index f7c99c67e..ad26064b9 100644 --- a/packages/inquirer/test/inquirer.test.mts +++ b/packages/inquirer/inquirer.test.mts @@ -10,11 +10,11 @@ import tty from 'node:tty'; import { vi, expect, beforeEach, afterEach, describe, it, expectTypeOf } from 'vitest'; import { Observable } from 'rxjs'; import type { InquirerReadline } from '@inquirer/type'; -import inquirer, { type QuestionMap } from '../src/index.mjs'; -import type { Answers, Question } from '../src/types.mjs'; -import { _ } from '../src/ui/prompt.mjs'; +import inquirer, { type QuestionMap } from './src/index.mjs'; +import type { Answers, Question } from './src/types.mjs'; +import { _ } from './src/ui/prompt.mjs'; -declare module '../src/index.mjs' { +declare module './src/index.mjs' { interface QuestionMap { stub: { answer?: string | boolean; message: string }; stub2: { answer?: string | boolean; message: string; default: string }; @@ -43,7 +43,7 @@ class StubPrompt { class StubFailingPrompt { run() { - return Promise.reject('This test prompt always reject'); + return Promise.reject(new Error('This test prompt always reject')); } close() {} @@ -635,13 +635,14 @@ describe('inquirer.prompt(...)', () => { it('should not run prompt if answer exists for question', async () => { const answers = await inquirer.prompt( + // @ts-expect-error Passing wrong type on purpose. [ { type: 'input', name: 'prefilled', - when: throwFunc.bind(undefined, 'when') as any, - validate: throwFunc.bind(undefined, 'validate') as any, - transformer: throwFunc.bind(undefined, 'transformer') as any, + when: throwFunc.bind(undefined, 'when'), + validate: throwFunc.bind(undefined, 'validate'), + transformer: throwFunc.bind(undefined, 'transformer'), message: 'message', default: 'newValue', }, @@ -654,13 +655,14 @@ describe('inquirer.prompt(...)', () => { it('should not run prompt if nested answer exists for question', async () => { const answers = await inquirer.prompt( + // @ts-expect-error Passing wrong type on purpose. [ { type: 'input', name: 'prefilled.nested', - when: throwFunc.bind(undefined, 'when') as any, - validate: throwFunc.bind(undefined, 'validate') as any, - transformer: throwFunc.bind(undefined, 'transformer') as any, + when: throwFunc.bind(undefined, 'when'), + validate: throwFunc.bind(undefined, 'validate'), + transformer: throwFunc.bind(undefined, 'transformer'), message: 'message', default: 'newValue', }, @@ -741,7 +743,7 @@ describe('inquirer.prompt(...)', () => { }); describe('#restoreDefaultPrompts()', () => { - it('restore default prompts', async () => { + it('restore default prompts', () => { class StubPrompt { run = vi.fn(() => { return Promise.resolve('bar'); @@ -891,6 +893,8 @@ describe('Non-TTY checks', () => { }); describe('set utility function tests', () => { + /* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access */ + it('Should set an objects property when provided a path and a value', () => { const obj: any = {}; const path = 'a.b'; @@ -931,4 +935,6 @@ describe('set utility function tests', () => { expect(obj.a.b).toBe('c'); }); + + /* eslint-enable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access */ }); diff --git a/packages/inquirer/src/index.mts b/packages/inquirer/src/index.mts index 2865859d1..6bedbeaf6 100644 --- a/packages/inquirer/src/index.mts +++ b/packages/inquirer/src/index.mts @@ -49,11 +49,9 @@ const defaultPrompts: PromptCollection = { search, }; -type PromptReturnType = - | (Promise> & { - ui: PromptsRunner>; - }) - | never; +type PromptReturnType = Promise> & { + ui: PromptsRunner>; +}; /** * Create a new self-contained prompt module. @@ -98,6 +96,7 @@ export function createPromptModule(opt?: StreamOptions) { try { return runner.run(questions, answers); } catch (error) { + // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors const promise = Promise.reject(error); return Object.assign(promise, { ui: runner }); } diff --git a/packages/inquirer/src/types.mts b/packages/inquirer/src/types.mts index e0d0f6b56..f531c4973 100644 --- a/packages/inquirer/src/types.mts +++ b/packages/inquirer/src/types.mts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { +import type { input, select, number, @@ -75,13 +75,13 @@ type PromptConfigMap = { export type Question = PromptConfigMap[keyof PromptConfigMap]; -export type QuestionAnswerMap = - | Readonly<{ [name in KeyUnion]: Omit, 'name'> }> - | never; +export type QuestionAnswerMap = Readonly<{ + [name in KeyUnion]: Omit, 'name'>; +}>; -export type QuestionArray = readonly Question[] | never; +export type QuestionArray = readonly Question[]; -export type QuestionObservable = Observable> | never; +export type QuestionObservable = Observable>; export type StreamOptions = Prettify< Parameters[1] & { skipTTYChecks?: boolean } diff --git a/packages/inquirer/src/ui/prompt.mts b/packages/inquirer/src/ui/prompt.mts index b5f41cd58..7d4d65fe5 100644 --- a/packages/inquirer/src/ui/prompt.mts +++ b/packages/inquirer/src/ui/prompt.mts @@ -26,8 +26,8 @@ import type { } from '../types.mjs'; export const _ = { - set: (obj: object, path: string = '', value: unknown): void => { - let pointer: any = obj; + set: (obj: Record, path: string = '', value: unknown): void => { + let pointer = obj; path.split('.').forEach((key, index, arr) => { if (key === '__proto__' || key === 'constructor') return; @@ -37,7 +37,7 @@ export const _ = { pointer[key] = {}; } - pointer = pointer[key]; + pointer = pointer[key] as Record; }); }, get: ( @@ -51,6 +51,7 @@ export const _ = { .filter(Boolean) .reduce( // @ts-expect-error implicit any on res[key] + // eslint-disable-next-line @typescript-eslint/no-unsafe-return (res, key) => (res !== null && res !== undefined ? res[key] : res), obj, ); @@ -72,7 +73,7 @@ function fetchAsyncQuestionProperty>( const propGetter = question[prop as keyof Q]; if (typeof propGetter === 'function') { return from( - runAsync(propGetter as (...args: any[]) => any)(answers).then((value) => { + runAsync(propGetter as (...args: unknown[]) => unknown)(answers).then((value) => { return Object.assign(question, { [prop]: value }); }), ); @@ -187,10 +188,11 @@ function isQuestionMap( function isPromptConstructor( prompt: PromptFn | LegacyPromptConstructor, ): prompt is LegacyPromptConstructor { - return ( + return Boolean( prompt.prototype && - 'run' in prompt.prototype && - typeof prompt.prototype.run === 'function' + 'run' in prompt.prototype && + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + typeof prompt.prototype.run === 'function', ); } @@ -244,14 +246,14 @@ export default class PromptsRunner { const promise = lastValueFrom( this.process.pipe( - reduce((answersObj, answer) => { + reduce((answersObj, answer: { name: string; answer: unknown }) => { _.set(answersObj, answer.name, answer.answer); return answersObj; }, this.answers), ), ).then( () => this.onCompletion(), - (error) => this.onError(error), + (error: Error) => this.onError(error), ) as Promise; return Object.assign(promise, { ui: this }); @@ -289,16 +291,19 @@ export default class PromptsRunner { fetchAsyncQuestionProperty(question, 'choices', this.answers), ), concatMap((question) => { - if ('choices' in question) { + const { choices } = question; + if (Array.isArray(choices)) { // @ts-expect-error question type is too loose - question.choices = question.choices.map((choice) => { - if (typeof choice === 'string' || typeof choice === 'number') { - return { name: choice, value: choice }; - } else if (!('value' in choice)) { - return { ...choice, value: choice.name }; - } - return choice; - }); + question.choices = choices.map( + (choice: string | number | { value?: string; name: string }) => { + if (typeof choice === 'string' || typeof choice === 'number') { + return { name: choice, value: choice }; + } else if (!('value' in choice)) { + return { ...choice, value: choice.name }; + } + return choice; + }, + ); } return of(question); @@ -340,7 +345,7 @@ export default class PromptsRunner { const activePrompt = new prompt(question, rl, this.answers); return from( - activePrompt.run().then((answer) => { + activePrompt.run().then((answer: unknown) => { onClose(); this.onClose = undefined; this.rl = undefined; @@ -351,7 +356,7 @@ export default class PromptsRunner { }) : defer(() => from( - prompt(question, this.opt).then((answer) => ({ + prompt(question, this.opt).then((answer: unknown) => ({ name: question.name, answer, })), diff --git a/packages/rawlist/src/index.mts b/packages/rawlist/src/index.mts index 958603b04..4796f9cbd 100644 --- a/packages/rawlist/src/index.mts +++ b/packages/rawlist/src/index.mts @@ -84,7 +84,7 @@ export default createPrompt( } index += 1; - const line = ` ${choice.key || index}) ${choice.name || choice.value}`; + const line = ` ${choice.key || index}) ${String(choice.name || choice.value)}`; if (choice.key === value.toLowerCase() || String(index) === value) { return theme.style.highlight(line); diff --git a/packages/search/search.test.mts b/packages/search/search.test.mts index ed35e7686..92a59f897 100644 --- a/packages/search/search.test.mts +++ b/packages/search/search.test.mts @@ -317,7 +317,7 @@ describe('search prompt', () => { it('allows default parameters to be used as source function parameters', async () => { const { answer } = await render(search, { message: 'Select a family', - source: async (term: string = '') => { + source: (term: string = '') => { expectTypeOf(term).toEqualTypeOf(); return []; }, diff --git a/packages/search/src/index.mts b/packages/search/src/index.mts index db39227a9..76b717a55 100644 --- a/packages/search/src/index.mts +++ b/packages/search/src/index.mts @@ -112,7 +112,7 @@ export default createPrompt( } }; - fetchResults(); + void fetchResults(); return () => { controller.abort(); @@ -122,7 +122,7 @@ export default createPrompt( // Safe to assume the cursor position never points to a Separator. const selectedChoice = searchResults[active] as Choice | void; - useKeypress(async (key, rl) => { + useKeypress((key, rl) => { if (isEnterKey(key) && selectedChoice) { setStatus('done'); done(selectedChoice.value); @@ -171,7 +171,7 @@ export default createPrompt( return ` ${item.separator}`; } - const line = item.name || item.value; + const line = String(item.name || item.value); if (item.disabled) { const disabledLabel = typeof item.disabled === 'string' ? item.disabled : '(disabled)'; diff --git a/packages/select/src/index.mts b/packages/select/src/index.mts index 4ceeee784..2c6a65ec0 100644 --- a/packages/select/src/index.mts +++ b/packages/select/src/index.mts @@ -182,7 +182,7 @@ export default createPrompt( return ` ${item.separator}`; } - const line = item.name || item.value; + const line = String(item.name || item.value); if (item.disabled) { const disabledLabel = typeof item.disabled === 'string' ? item.disabled : '(disabled)'; diff --git a/packages/testing/src/index.mts b/packages/testing/src/index.mts index dd47202e9..340478c6b 100644 --- a/packages/testing/src/index.mts +++ b/packages/testing/src/index.mts @@ -87,11 +87,11 @@ export async function render< answer, input, events, - getScreen({ raw }: { raw?: boolean } = {}): string { + getScreen: ({ raw }: { raw?: boolean } = {}): string => { const lastScreen = output.getLastChunk({ raw }); return raw ? lastScreen : stripAnsi(lastScreen).trim(); }, - getFullOutput(): string { + getFullOutput: (): string => { return output.getFullOutput(); }, }; diff --git a/packages/type/src/utils.mts b/packages/type/src/utils.mts index f3231ef7f..98782c2b0 100644 --- a/packages/type/src/utils.mts +++ b/packages/type/src/utils.mts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ type Key = string | number | symbol; diff --git a/yarn.lock b/yarn.lock index b134b9619..daa6a16ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -601,7 +601,7 @@ __metadata: ts-node: "npm:^10.9.2" turbo: "npm:^2.0.11" typescript: "npm:^5.5.4" - typescript-eslint: "npm:^7.18.0" + typescript-eslint: "npm:^8.0.0" vitest: "npm:^2.0.5" languageName: unknown linkType: soft @@ -1644,87 +1644,85 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.18.0" +"@typescript-eslint/eslint-plugin@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.0.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:7.18.0" - "@typescript-eslint/type-utils": "npm:7.18.0" - "@typescript-eslint/utils": "npm:7.18.0" - "@typescript-eslint/visitor-keys": "npm:7.18.0" + "@typescript-eslint/scope-manager": "npm:8.0.0" + "@typescript-eslint/type-utils": "npm:8.0.0" + "@typescript-eslint/utils": "npm:8.0.0" + "@typescript-eslint/visitor-keys": "npm:8.0.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^1.3.0" peerDependencies: - "@typescript-eslint/parser": ^7.0.0 - eslint: ^8.56.0 + "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/6ee4c61f145dc05f0a567b8ac01b5399ef9c75f58bc6e9a3ffca8927b15e2be2d4c3fd32a2c1a7041cc0848fdeadac30d9cb0d3bcd3835d301847a88ffd19c4d + checksum: 10/80c52b37f8c3489a637cbb433ffce19e7d279bd20bd4ccd0db9e3647afd6d2e7643c8319feafa5907c62c460c48605ca87e12a9c7890a094f264f47e2579add4 languageName: node linkType: hard -"@typescript-eslint/parser@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/parser@npm:7.18.0" +"@typescript-eslint/parser@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/parser@npm:8.0.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.18.0" - "@typescript-eslint/types": "npm:7.18.0" - "@typescript-eslint/typescript-estree": "npm:7.18.0" - "@typescript-eslint/visitor-keys": "npm:7.18.0" + "@typescript-eslint/scope-manager": "npm:8.0.0" + "@typescript-eslint/types": "npm:8.0.0" + "@typescript-eslint/typescript-estree": "npm:8.0.0" + "@typescript-eslint/visitor-keys": "npm:8.0.0" debug: "npm:^4.3.4" peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/36b00e192a96180220ba100fcce3c777fc3e61a6edbdead4e6e75a744d9f0cbe3fabb5f1c94a31cce6b28a4e4d5de148098eec01296026c3c8e16f7f0067cb1e + checksum: 10/044a7deb299bc988b7f33a99b9c1dc387133e7ce4b2f7751568e4fd07a2e541c1d628e332205ac3cbd797fcad95f89d097a38e6e7e42707d9022fbf0b8b26e6c languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/scope-manager@npm:7.18.0" +"@typescript-eslint/scope-manager@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/scope-manager@npm:8.0.0" dependencies: - "@typescript-eslint/types": "npm:7.18.0" - "@typescript-eslint/visitor-keys": "npm:7.18.0" - checksum: 10/9eb2ae5d69d9f723e706c16b2b97744fc016996a5473bed596035ac4d12429b3d24e7340a8235d704efa57f8f52e1b3b37925ff7c2e3384859d28b23a99b8bcc + "@typescript-eslint/types": "npm:8.0.0" + "@typescript-eslint/visitor-keys": "npm:8.0.0" + checksum: 10/444dbc156d9d6d2aa4f82e35ab171aed85d1818c5adf70f955f69d6d0591d9a0668f645d38bf5b759098849aa4114340ca128a673be5525a94fba9a048751d0c languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/type-utils@npm:7.18.0" +"@typescript-eslint/type-utils@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/type-utils@npm:8.0.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.18.0" - "@typescript-eslint/utils": "npm:7.18.0" + "@typescript-eslint/typescript-estree": "npm:8.0.0" + "@typescript-eslint/utils": "npm:8.0.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" - peerDependencies: - eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/bcc7958a4ecdddad8c92e17265175773e7dddf416a654c1a391e69cb16e43960b39d37b6ffa349941bf3635e050f0ca7cd8f56ec9dd774168f2bbe7afedc9676 + checksum: 10/89ca36511acdb8d45dfe524ac6e06dbee4dea04ac02af2dd7e42de1fedd33aff8e88a08a2407259fc4f10220f90363856d9cee419697dd1381ea7b3d0b19af69 languageName: node linkType: hard -"@typescript-eslint/types@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/types@npm:7.18.0" - checksum: 10/0e30c73a3cc3c67dd06360a5a12fd12cee831e4092750eec3d6c031bdc4feafcb0ab1d882910a73e66b451a4f6e1dd015e9e2c4d45bf6bf716a474e5d123ddf0 +"@typescript-eslint/types@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/types@npm:8.0.0" + checksum: 10/e28e79d8b7acfa42c90781fa63e90e56807ae018a0a92fc71c8e441d2bb3a250527c9d44ff6450ff1d47ceed0c3df28de6599f97f6c4c65ac554088867fc3517 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.18.0" +"@typescript-eslint/typescript-estree@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.0.0" dependencies: - "@typescript-eslint/types": "npm:7.18.0" - "@typescript-eslint/visitor-keys": "npm:7.18.0" + "@typescript-eslint/types": "npm:8.0.0" + "@typescript-eslint/visitor-keys": "npm:8.0.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -1734,31 +1732,31 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/b01e66235a91aa4439d02081d4a5f8b4a7cf9cb24f26b334812f657e3c603493e5f41e5c1e89cf4efae7d64509fa1f73affc16afc5e15cb7f83f724577c82036 + checksum: 10/99a80fb43d1e9cbd49a3dfdd264e7e361ffd4e19970d2b04b86a551fc730cc4f19202c3323d0d6bbfd7ce4672bf205cb7b756ba2e20c95729b24e878b96e66f3 languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/utils@npm:7.18.0" +"@typescript-eslint/utils@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/utils@npm:8.0.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:7.18.0" - "@typescript-eslint/types": "npm:7.18.0" - "@typescript-eslint/typescript-estree": "npm:7.18.0" + "@typescript-eslint/scope-manager": "npm:8.0.0" + "@typescript-eslint/types": "npm:8.0.0" + "@typescript-eslint/typescript-estree": "npm:8.0.0" peerDependencies: - eslint: ^8.56.0 - checksum: 10/f43fedb4f4d2e3836bdf137889449063a55c0ece74fdb283929cd376197b992313be8ef4df920c1c801b5c3076b92964c84c6c3b9b749d263b648d0011f5926e + eslint: ^8.57.0 || ^9.0.0 + checksum: 10/f76e65763725d944d3c6f0e78ea566cdb08247fa7ee9e2ec15310527f3e2325c92cb67c80a63e4a6dd29a5a7d96db3839aebd0a2e98810dcc248f6762414c995 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.18.0": - version: 7.18.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.18.0" +"@typescript-eslint/visitor-keys@npm:8.0.0": + version: 8.0.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.0.0" dependencies: - "@typescript-eslint/types": "npm:7.18.0" + "@typescript-eslint/types": "npm:8.0.0" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10/b7cfe6fdeae86c507357ac6b2357813c64fb2fbf1aaf844393ba82f73a16e2599b41981b34200d9fc7765d70bc3a8181d76b503051e53f04bcb7c9afef637eab + checksum: 10/328106878ed42f1543590317477275a3c95c0455ba8203355fede94b0970844ec430cc5e090d4e1f48d805ac40ab1bd339270514e256b0810cabd423c6b2d52a languageName: node linkType: hard @@ -8113,19 +8111,17 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^7.18.0": - version: 7.18.0 - resolution: "typescript-eslint@npm:7.18.0" +"typescript-eslint@npm:^8.0.0": + version: 8.0.0 + resolution: "typescript-eslint@npm:8.0.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:7.18.0" - "@typescript-eslint/parser": "npm:7.18.0" - "@typescript-eslint/utils": "npm:7.18.0" - peerDependencies: - eslint: ^8.56.0 + "@typescript-eslint/eslint-plugin": "npm:8.0.0" + "@typescript-eslint/parser": "npm:8.0.0" + "@typescript-eslint/utils": "npm:8.0.0" peerDependenciesMeta: typescript: optional: true - checksum: 10/7c1ad00ecd7141d8631a99ff602cfabdab3d9f8a9be5b0282b8b3291125df1fc37c4baa13d1ef26562de8ed1393a5851a7e861ded0224127fe670ffae6fed6aa + checksum: 10/128c1ff75dc6e6e79fbd93aff615a0c2a7abeeca507bc667689d805a1498e8c671277dbd3f31396fafad633ed82b6f7300686a6dea355e6f99f9c7dfb8918a21 languageName: node linkType: hard