From 73e49dde53301952d4e48b330c33be118e83fa85 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 17 Nov 2025 09:35:03 -0800 Subject: [PATCH 1/8] Fix VS Code types (#74099) --- types/vscode/.eslintrc.json | 5 +++-- types/vscode/package.json | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/types/vscode/.eslintrc.json b/types/vscode/.eslintrc.json index 73aec260e54d13..0d4ac1b1071e36 100644 --- a/types/vscode/.eslintrc.json +++ b/types/vscode/.eslintrc.json @@ -6,9 +6,10 @@ "@definitelytyped/strict-export-declare-modifiers": "off", "@definitelytyped/no-single-declare-module": "off", "@typescript-eslint/no-unsafe-function-type": "off", -"@typescript-eslint/no-wrapper-object-types": "off", + "@typescript-eslint/no-wrapper-object-types": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-invalid-void-type": "off", - "@typescript-eslint/array-type": "off" + "@typescript-eslint/array-type": "off", + "jsdoc/check-tag-names": "off" } } diff --git a/types/vscode/package.json b/types/vscode/package.json index 4de8dbb145fb90..cd330d2d39b8f1 100644 --- a/types/vscode/package.json +++ b/types/vscode/package.json @@ -2,6 +2,8 @@ "private": true, "name": "@types/vscode", "version": "1.106.9999", + "nonNpm": "conflict", + "nonNpmDescription": "TypeScript definitions for the Visual Studio Code Extension API", "projects": [ "https://github.com/microsoft/vscode" ], @@ -14,4 +16,4 @@ "githubUsername": "microsoft" } ] -} \ No newline at end of file +} From df395d71b386395a089276b3f46cd91561fcb3cb Mon Sep 17 00:00:00 2001 From: chcederquist Date: Mon, 17 Nov 2025 21:23:54 +0100 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74058=20Types?= =?UTF-8?q?=20for=20the=20package=20"dkfds"=20by=20@chcederquist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/dkfds/.npmignore | 5 + types/dkfds/dkfds-tests.ts | 249 ++++++++++++++++++++++++++++++++++ types/dkfds/index.d.ts | 265 +++++++++++++++++++++++++++++++++++++ types/dkfds/package.json | 17 +++ types/dkfds/tsconfig.json | 20 +++ 5 files changed, 556 insertions(+) create mode 100644 types/dkfds/.npmignore create mode 100644 types/dkfds/dkfds-tests.ts create mode 100644 types/dkfds/index.d.ts create mode 100644 types/dkfds/package.json create mode 100644 types/dkfds/tsconfig.json diff --git a/types/dkfds/.npmignore b/types/dkfds/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/dkfds/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/dkfds/dkfds-tests.ts b/types/dkfds/dkfds-tests.ts new file mode 100644 index 00000000000000..64a9be06d42004 --- /dev/null +++ b/types/dkfds/dkfds-tests.ts @@ -0,0 +1,249 @@ +import * as DKFDS from "dkfds"; + +// Test init function +DKFDS.init({ scope: document.body }); // $ExpectType void +DKFDS.init({ scope: document.getElementById("app")! }); // $ExpectType void + +// Test Accordion +const accordionElement = document.createElement("ul"); +const accordionStrings = { open_all: "Åbn alle", close_all: "Luk alle" }; + +const accordion1 = new DKFDS.Accordion(accordionElement, accordionStrings); // $ExpectType Accordion + +accordion1.init(); // $ExpectType void +accordion1.bulkEvent(); // $ExpectType void + +const button = document.createElement("button"); +const pointerEvent = new PointerEvent("click"); +accordion1.eventOnClick(button, pointerEvent); // $ExpectType void +accordion1.toggleButton(button); // $ExpectType void +accordion1.toggleButton(button, true); // $ExpectType void +accordion1.toggleButton(button, false, true); // $ExpectType void + +// Test DatePicker +const datePickerEl = document.createElement("div"); + +DKFDS.datePicker.init(datePickerEl); // $ExpectType void +DKFDS.datePicker.add(datePickerEl); // $ExpectType void +DKFDS.datePicker.on(datePickerEl); // $ExpectType void +DKFDS.datePicker.off(datePickerEl); // $ExpectType void + +DKFDS.datePicker.setLanguage({ + open_calendar: "Åbn kalender", + choose_a_date: "Vælg en dato", + choose_a_date_between: "Vælg en dato mellem", + choose_a_date_before: "Vælg en dato før", + choose_a_date_after: "Vælg en dato efter", + aria_label_date: "Dato", + current_month_displayed: "Nuværende måned vist", + first_possible_date: "Første mulige dato", + last_possible_date: "Sidste mulige dato", + previous_year: "Forrige år", + previous_month: "Forrige måned", + next_month: "Næste måned", + next_year: "Næste år", + select_month: "Vælg måned", + select_year: "Vælg år", + previous_years: "Forrige år", + next_years: "Næste år", + guide: "Vejledning", + months_displayed: "Måneder vist", + years_displayed: "År vist", + january: "Januar", + february: "Februar", + march: "Marts", + april: "April", + may: "Maj", + june: "Juni", + july: "Juli", + august: "August", + september: "September", + october: "Oktober", + november: "November", + december: "December", + monday: "Mandag", + tuesday: "Tirsdag", + wednesday: "Onsdag", + thursday: "Torsdag", + friday: "Fredag", + saturday: "Lørdag", + sunday: "Søndag", +}); + +DKFDS.datePicker.disable(datePickerEl); // $ExpectType void +DKFDS.datePicker.enable(datePickerEl); // $ExpectType void + +DKFDS.datePicker.isDateInputInvalid(datePickerEl); // $ExpectType boolean + +DKFDS.datePicker.setCalendarValue(datePickerEl, "2023-12-31"); // $ExpectType void +DKFDS.datePicker.validateDateInput(datePickerEl); // $ExpectType void + +DKFDS.datePicker.renderCalendar(datePickerEl); // $ExpectType HTMLElement +DKFDS.datePicker.renderCalendar(datePickerEl, new Date()); // $ExpectType HTMLElement + +DKFDS.datePicker.updateCalendarIfVisible(datePickerEl); // $ExpectType void + +const context = DKFDS.datePicker.getDatePickerContext(datePickerEl); // $ExpectType DatePickerContext | undefined +if (context) { + context.calendarEl; // $ExpectType HTMLDivElement + context.datePickerEl; // $ExpectType HTMLElement + context.dialogEl; // $ExpectType HTMLDivElement + context.internalInputEl; // $ExpectType HTMLInputElement + context.externalInputEl; // $ExpectType HTMLInputElement + context.statusEl; // $ExpectType HTMLDivElement + context.guideEl; // $ExpectType HTMLDivElement + context.firstYearChunkEl; // $ExpectType HTMLDivElement + context.calendarDate; // $ExpectType Date + context.minDate; // $ExpectType Date + context.maxDate; // $ExpectType Date + context.selectedDate; // $ExpectType Date + context.rangeDate; // $ExpectType Date + context.defaultDate; // $ExpectType Date +} + +// Test Tooltip +const tooltipWrapper = document.createElement("div"); + +const tooltip1 = new DKFDS.Tooltip(tooltipWrapper); // $ExpectType Tooltip + +tooltip1.init(); // $ExpectType void +tooltip1.hideTooltip(); // $ExpectType void +tooltip1.showTooltip(); // $ExpectType void + +tooltip1.isShowing(); // $ExpectType boolean +tooltip1.updateTooltipPosition(); // $ExpectType void + +// Test Alert +const alertElement = document.createElement("div"); + +const alert1 = new DKFDS.Alert(alertElement); // $ExpectType Alert + +alert1.init(); // $ExpectType void +alert1.hide(); // $ExpectType void +alert1.show(); // $ExpectType void + +// Test BackToTop +const backToTopElement = document.createElement("div"); + +const backToTop1 = new DKFDS.BackToTop(backToTopElement); // $ExpectType BackToTop + +backToTop1.init(); // $ExpectType void + +// Test CharacterLimit +const charLimitElement = document.createElement("div"); +const charLimitStrings = { + character_remaining: "tegn tilbage", + characters_remaining: "tegn tilbage", + character_too_many: "tegn for meget", + characters_too_many: "tegn for meget", +}; + +const charLimit1 = new DKFDS.CharacterLimit(charLimitElement, charLimitStrings); // $ExpectType CharacterLimit + +charLimit1.init(); // $ExpectType void + +// Test CheckboxToggleContent +const checkboxInput = document.createElement("input"); + +const checkboxToggle1 = new DKFDS.CheckboxToggleContent(checkboxInput); // $ExpectType CheckboxToggleContent + +checkboxToggle1.init(); // $ExpectType void +checkboxToggle1.toggle(); // $ExpectType void + +const contentElement = document.createElement("div"); +checkboxToggle1.expand(checkboxInput, contentElement); // $ExpectType void +checkboxToggle1.collapse(checkboxInput, contentElement); // $ExpectType void + +// Test Dropdown +const dropdownButton = document.createElement("button"); + +const dropdown1 = new DKFDS.Dropdown(dropdownButton); // $ExpectType Dropdown + +dropdown1.init(); // $ExpectType void +dropdown1.hide(); // $ExpectType void +dropdown1.show(); // $ExpectType void + +// Test ErrorSummary +const errorSummaryElement = document.createElement("div"); + +const errorSummary1 = new DKFDS.ErrorSummary(errorSummaryElement); // $ExpectType ErrorSummary + +errorSummary1.init(); // $ExpectType void + +const mouseEvent = new MouseEvent("click"); +errorSummary1.handleClick(mouseEvent); // $ExpectType void + +const targetElement = document.createElement("div"); +errorSummary1.focusTarget(targetElement); // $ExpectType boolean + +errorSummary1.getFragmentFromUrl("http://example.com#test"); // $ExpectType string | false + +const inputElement = document.createElement("input"); +errorSummary1.getAssociatedLegendOrLabel(inputElement); // $ExpectType HTMLElement | null + +// Test Modal +const modalElement = document.createElement("div"); + +const modal1 = new DKFDS.Modal(modalElement); // $ExpectType Modal + +modal1.init(); // $ExpectType void +modal1.hide(); // $ExpectType void +modal1.show(); // $ExpectType void + +// Test MenuDropdown +const menuButton = document.createElement("button"); + +const menuDropdown1 = new DKFDS.MenuDropdown(menuButton); // $ExpectType MenuDropdown + +menuDropdown1.init(); // $ExpectType void +menuDropdown1.hide(); // $ExpectType void +menuDropdown1.show(); // $ExpectType void + +// Test Navigation +const navigation = new DKFDS.Navigation(); // $ExpectType Navigation +navigation.init(); // $ExpectType void +navigation.teardown(); // $ExpectType void + +// Test RadioToggleGroup +const radioContainer = document.createElement("div"); + +const radioToggle1 = new DKFDS.RadioToggleGroup(radioContainer); // $ExpectType RadioToggleGroup + +radioToggle1.init(); // $ExpectType void + +const radioInput = document.createElement("input"); +radioToggle1.toggle(radioInput); // $ExpectType void +radioToggle1.expand(radioInput, contentElement); // $ExpectType void +radioToggle1.collapse(radioInput, contentElement); // $ExpectType void + +// Test TableSelectableRows +const tableElement = document.createElement("table"); + +const tableSelectable1 = new DKFDS.TableSelectableRows(tableElement); // $ExpectType TableSelectableRows + +tableSelectable1.init(); // $ExpectType void + +tableSelectable1.getGroupCheckbox(); // $ExpectType false | HTMLElement +tableSelectable1.getCheckboxList(); // $ExpectType HTMLCollection + +// Test ResponsiveTable +const responsiveTable = new DKFDS.ResponsiveTable(tableElement); // $ExpectType ResponsiveTable + +// Test Tabs +const tabsElement = document.createElement("div"); + +const tabs1 = new DKFDS.Tabs(tabsElement); // $ExpectType Tabs + +tabs1.init(); // $ExpectType void + +const tabButton = document.createElement("button"); +tabs1.activateTab(tabButton, true); // $ExpectType void +tabs1.activateTab(tabButton, false); // $ExpectType void + +// Test Toast +const toastElement = document.createElement("div"); + +const toast1 = new DKFDS.Toast(toastElement); // $ExpectType Toast + +toast1.show(); // $ExpectType void +toast1.hide(); // $ExpectType void diff --git a/types/dkfds/index.d.ts b/types/dkfds/index.d.ts new file mode 100644 index 00000000000000..b106ba43805868 --- /dev/null +++ b/types/dkfds/index.d.ts @@ -0,0 +1,265 @@ +export class Accordion { + constructor($accordion: HTMLElement, strings: { open_all: string; close_all: string }); + + bulkEvent(): void; + + eventOnClick($button: HTMLButtonElement, e: PointerEvent): void; + + init(): void; + + toggleButton(button: HTMLButtonElement, expanded?: boolean, bulk?: boolean): void; +} + +export class Alert { + constructor(element: HTMLElement); + + hide(): void; + + init(): void; + + show(): void; +} + +export class BackToTop { + constructor(element: HTMLElement); + + init(): void; +} + +export class CharacterLimit { + constructor( + element: HTMLElement, + strings: { + character_remaining: string; + characters_remaining: string; + character_too_many: string; + characters_too_many: string; + }, + ); + + charactersLeft(): number; + + silentUpdateMessages(): void; + + updateMessages(): void; + + init(): void; +} + +export class CheckboxToggleContent { + constructor(element: HTMLInputElement); + + collapse(triggerEl: HTMLInputElement, targetEl: HTMLElement): void; + + expand(checkboxElement: HTMLInputElement, contentElement: HTMLElement): void; + + init(): void; + + toggle(): void; +} + +export class Dropdown { + constructor(element: HTMLButtonElement); + + hide(): void; + + init(): void; + + show(): void; +} + +export class DropdownSort { + constructor(container: HTMLElement); + + init(): void; + + onOptionClick(e: PointerEvent): void; + + updateSelectedValue(): void; +} + +export class ErrorSummary { + constructor(element: HTMLElement); + focusTarget($target: HTMLElement): boolean; + + getAssociatedLegendOrLabel($input: HTMLElement): HTMLElement | null; + + getFragmentFromUrl(url: string): string | false; + + handleClick(e: MouseEvent): void; + + init(): void; +} + +export class MenuDropdown { + constructor(element: HTMLButtonElement); + + hide(): void; + + init(): void; + + show(): void; +} + +export class Modal { + constructor(element: HTMLElement); + + hide(): void; + + init(): void; + + show(): void; +} + +export class Navigation { + init(): void; + + teardown(): void; +} + +export class RadioToggleGroup { + constructor(containerElement: HTMLElement); + + collapse(triggerEl: HTMLInputElement, targetEl: HTMLElement): void; + + expand(checkboxElement: HTMLInputElement, contentElement: HTMLElement): void; + + init(): void; + + toggle(radioInputElement: HTMLInputElement): void; +} + +export class TableSelectableRows { + constructor(tableElement: HTMLTableElement); + + getCheckboxList(): HTMLCollection; + + getGroupCheckbox(): HTMLElement | false; + + init(): void; +} + +export class Tabs { + constructor(element: HTMLElement); + + activateTab(tab: HTMLButtonElement, setFocus: boolean): void; + + init(): void; +} + +export class Toast { + constructor(element: HTMLElement); + + hide(): void; + + show(): void; +} + +export class Tooltip { + constructor(wrapper: HTMLElement); + + hideTooltip(): void; + + init(): void; + + isShowing(): boolean; + + showTooltip(): void; + + updateTooltipPosition(): void; +} + +export class ResponsiveTable { + constructor(table: HTMLTableElement); +} + +export function init(options?: { scope: HTMLElement }): void; + +export interface DatePickerContext { + calendarEl: HTMLDivElement; + datePickerEl: HTMLElement; + dialogEl: HTMLDivElement; + internalInputEl: HTMLInputElement; + externalInputEl: HTMLInputElement; + statusEl: HTMLDivElement; + guideEl: HTMLDivElement; + firstYearChunkEl: HTMLDivElement; + calendarDate: Date; + minDate: Date; + maxDate: Date; + selectedDate: Date; + rangeDate: Date; + defaultDate: Date; +} + +export const datePicker: { + add(root: HTMLElement): void; + + disable(element: HTMLElement): void; + + enable(element: HTMLElement): void; + + getDatePickerContext(element: HTMLElement): DatePickerContext | undefined; + + init(root: HTMLElement): void; + + isDateInputInvalid(element: HTMLElement): boolean; + + off(root: HTMLElement): void; + + on(root: HTMLElement): void; + + remove(root: HTMLElement): void; + + renderCalendar(el: HTMLElement, _dateToDisplay?: Date): HTMLElement; + + setCalendarValue(el: HTMLElement, dateString: string): void; + + setLanguage(language: { + open_calendar: string; + choose_a_date: string; + choose_a_date_between: string; + choose_a_date_before: string; + choose_a_date_after: string; + aria_label_date: string; + current_month_displayed: string; + first_possible_date: string; + last_possible_date: string; + previous_year: string; + previous_month: string; + next_month: string; + next_year: string; + select_month: string; + select_year: string; + previous_years: string; + next_years: string; + guide: string; + months_displayed: string; + years_displayed: string; + january: string; + february: string; + march: string; + april: string; + may: string; + june: string; + july: string; + august: string; + september: string; + october: string; + november: string; + december: string; + monday: string; + tuesday: string; + wednesday: string; + thursday: string; + friday: string; + saturday: string; + sunday: string; + }): void; + + updateCalendarIfVisible(el: HTMLElement): void; + + validateDateInput(el: HTMLElement): void; +}; + +export as namespace DKFDS; diff --git a/types/dkfds/package.json b/types/dkfds/package.json new file mode 100644 index 00000000000000..77d2f1d51c522b --- /dev/null +++ b/types/dkfds/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@types/dkfds", + "version": "11.1.9999", + "projects": [ + "https://designsystem.dk/" + ], + "devDependencies": { + "@types/dkfds": "workspace:." + }, + "owners": [ + { + "name": "Christian Pilegaard Cederquist", + "githubUsername": "chcederquist" + } + ] +} diff --git a/types/dkfds/tsconfig.json b/types/dkfds/tsconfig.json new file mode 100644 index 00000000000000..0c4a3b6443dc2c --- /dev/null +++ b/types/dkfds/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "dkfds-tests.ts" + ] +} From e1b43e59d6f37b7ed158bb388cc5e1cb42d42065 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 17 Nov 2025 13:17:54 -0800 Subject: [PATCH 3/8] [webgl2] mark as npm conflicting (#74102) --- types/webgl2/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/webgl2/package.json b/types/webgl2/package.json index 3cbcd1a26fbc79..6cba7cd8dc91fc 100644 --- a/types/webgl2/package.json +++ b/types/webgl2/package.json @@ -2,7 +2,7 @@ "private": true, "name": "@types/webgl2", "version": "0.0.9999", - "nonNpm": true, + "nonNpm": "conflict", "nonNpmDescription": "webgl2", "projects": [ "https://www.khronos.org/registry/webgl/specs/latest/2.0/" From 20fcea7794746f1d5cdd5a50f04b25d4f5cb9d77 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Tue, 18 Nov 2025 05:21:14 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74084=20feat(v?= =?UTF-8?q?alidator):=20make=20isRgbColor()=20accept=20boolean=20in=202nd?= =?UTF-8?q?=20arg=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isRgbColor.d.ts | 1 + types/validator/index.d.ts | 2 +- types/validator/lib/isRgbColor.d.ts | 1 + types/validator/validator-tests.ts | 14 ++++++++------ 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/types/validator/es/lib/isRgbColor.d.ts b/types/validator/es/lib/isRgbColor.d.ts index 45180093b53228..db101b84f546e5 100644 --- a/types/validator/es/lib/isRgbColor.d.ts +++ b/types/validator/es/lib/isRgbColor.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsRgbColorOptions = validator.IsRgbColorOptions; export default validator.isRgbColor; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index fbeb2cd7ac23ec..95d7d759c720e7 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -631,7 +631,7 @@ declare namespace validator { * * @param [options] - Options */ - export function isRgbColor(str: string, options?: IsRgbColorOptions): boolean; + export function isRgbColor(str: string, includePercentValuesOrOptions?: boolean | IsRgbColorOptions): boolean; export type IdentityCardLocale = | "ar-LY" diff --git a/types/validator/lib/isRgbColor.d.ts b/types/validator/lib/isRgbColor.d.ts index 7251e4fd1a331a..c24cbaa6303ae4 100644 --- a/types/validator/lib/isRgbColor.d.ts +++ b/types/validator/lib/isRgbColor.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsRgbColorOptions = validator.IsRgbColorOptions; export default validator.isRgbColor; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 41374e69dc8de9..250bb13945a2f1 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -78,7 +78,7 @@ import isOctalFunc from "validator/lib/isOctal"; import isPassportNumberFunc from "validator/lib/isPassportNumber"; import isPortFunc from "validator/lib/isPort"; import isPostalCodeFunc, { locales as isPostalCodeLocales } from "validator/lib/isPostalCode"; -import isRgbColorFunc from "validator/lib/isRgbColor"; +import isRgbColorFunc, { IsRgbColorOptions } from "validator/lib/isRgbColor"; import isSemVerFunc from "validator/lib/isSemVer"; import isSlugFunc from "validator/lib/isSlug"; import isStrongPasswordFunc from "validator/lib/isStrongPassword"; @@ -488,7 +488,7 @@ import isOctalFuncEs from "validator/es/lib/isOctal"; import isPassportNumberFuncEs from "validator/es/lib/isPassportNumber"; import isPortFuncEs from "validator/es/lib/isPort"; import isPostalCodeFuncEs, { locales as isPostalCodeLocalesEs } from "validator/es/lib/isPostalCode"; -import isRgbColorFuncEs from "validator/es/lib/isRgbColor"; +import isRgbColorFuncEs, { IsRgbColorOptions as IsRgbColorOptionsEs } from "validator/es/lib/isRgbColor"; import isSemVerFuncEs from "validator/es/lib/isSemVer"; import isSlugFuncEs from "validator/es/lib/isSlug"; import isStrongPasswordFuncEs from "validator/es/lib/isStrongPassword"; @@ -900,10 +900,12 @@ const any: any = null; result = validator.isHSL("sample"); result = validator.isRgbColor("sample"); - result = validator.isRgbColor("sample", { includePercentValues: true }); - result = validator.isRgbColor("sample", { includePercentValues: false }); - result = validator.isRgbColor("sample", { includePercentValues: true, allowSpaces: true }); - result = validator.isRgbColor("sample", { allowSpaces: false }); + result = validator.isRgbColor("sample", true); + result = validator.isRgbColor("sample", {}); + result = validator.isRgbColor( + "sample", + { includePercentValues: true, allowSpaces: true } satisfies IsRgbColorOptions, + ); result = validator.isHexadecimal("sample"); From 515ca79df9611fa2624ad3dba62ef3c262bd8188 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Tue, 18 Nov 2025 05:24:23 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74089=20feat(v?= =?UTF-8?q?alidator):=20make=20isDate()=20accept=20Date=20in=201st=20arg?= =?UTF-8?q?=20&=20format=20string=20in=202nd=20arg=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/es/lib/isDate.d.ts | 1 + types/validator/index.d.ts | 3 ++- types/validator/lib/isDate.d.ts | 1 + types/validator/validator-tests.ts | 27 +++++++++++++++++++++++---- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/types/validator/es/lib/isDate.d.ts b/types/validator/es/lib/isDate.d.ts index 448bf243fc457d..79f74f6d40e221 100644 --- a/types/validator/es/lib/isDate.d.ts +++ b/types/validator/es/lib/isDate.d.ts @@ -1,2 +1,3 @@ import validator from "../../"; +export type IsDateOptions = validator.IsDateOptions; export default validator.isDate; diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 95d7d759c720e7..4a1d991a33b857 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -417,7 +417,8 @@ declare namespace validator { /** * Check if the string is a valid date. */ - export function isDate(str: string, options?: IsDateOptions): boolean; + export function isDate(input: Date, formatOrOptions: IsDateOptions & { strictMode: true }): false; + export function isDate(input: string | Date, formatOrOptions?: string | IsDateOptions): boolean; export type DecimalLocale = FloatLocale; diff --git a/types/validator/lib/isDate.d.ts b/types/validator/lib/isDate.d.ts index 56de8bec17e21d..4d2229329e1d7b 100644 --- a/types/validator/lib/isDate.d.ts +++ b/types/validator/lib/isDate.d.ts @@ -1,2 +1,3 @@ import validator from "../"; +export type IsDateOptions = validator.IsDateOptions; export default validator.isDate; diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index 250bb13945a2f1..f1d2db4e293526 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -25,7 +25,7 @@ import isByteLengthFunc, { IsByteLengthOptions } from "validator/lib/isByteLengt import isCreditCardFunc from "validator/lib/isCreditCard"; import isCurrencyFunc from "validator/lib/isCurrency"; import isDataURIFunc from "validator/lib/isDataURI"; -import isDateFunc from "validator/lib/isDate"; +import isDateFunc, { IsDateOptions } from "validator/lib/isDate"; import isDecimalFunc from "validator/lib/isDecimal"; import isDivisibleByFunc from "validator/lib/isDivisibleBy"; import isEANFunc from "validator/lib/isEAN"; @@ -432,7 +432,7 @@ import isByteLengthFuncEs, { IsByteLengthOptions as IsByteLengthOptionsEs } from import isCreditCardFuncEs from "validator/es/lib/isCreditCard"; import isCurrencyFuncEs from "validator/es/lib/isCurrency"; import isDataURIFuncEs from "validator/es/lib/isDataURI"; -import isDateFuncEs from "validator/es/lib/isDate"; +import isDateFuncEs, { IsDateOptions as IsDateOptionsEs } from "validator/es/lib/isDate"; import isDecimalFuncEs from "validator/es/lib/isDecimal"; import isDivisibleByFuncEs from "validator/es/lib/isDivisibleBy"; import isEANFuncEs from "validator/es/lib/isEAN"; @@ -788,9 +788,28 @@ const any: any = null; result = validator.isDataURI("sample"); - const isDateOptions: validator.IsDateOptions = {}; result = validator.isDate("sample"); - result = validator.isDate("sample", isDateOptions); + result = validator.isDate("sample", "YYYY/MM/DD"); + result = validator.isDate("sample", {} satisfies IsDateOptions); + result = validator.isDate("sample", { format: "YYYY/MM/DD", delimiters: ["/", "-"], strictMode: false }); + validator.isDate("sample", { strictMode: true }); // $ExpectType boolean + validator.isDate("sample", { strictMode: false }); // $ExpectType boolean + validator.isDate("sample", { strictMode: result }); // $ExpectType boolean + + result = validator.isDate(new Date()); + result = validator.isDate(new Date(), "YYYY/MM/DD"); + result = validator.isDate(new Date(), {} satisfies IsDateOptions); + result = validator.isDate(new Date(), { format: "YYYY/MM/DD", delimiters: ["/", "-"], strictMode: false }); + // If options.strictMode is known to be true in compile time, we return false. + validator.isDate(new Date(), { strictMode: true }); // $ExpectType false + // If options.strictMode is false or unknown in compile time, we return a boolean type as fallback + validator.isDate(new Date(), { strictMode: false }); // $ExpectType boolean + validator.isDate(new Date(), { strictMode: result }); // $ExpectType boolean + // Let's test for union type as well. + result = validator.isDate( + result ? "sample" : new Date(), + result ? "YYYY/MM/DD" : { format: "YYYY/MM/DD", delimiters: ["/", "-"], strictMode: false }, + ); const isDecimalOptions: validator.IsDecimalOptions = {}; result = validator.isDecimal("sample"); From 68e65580ed7aac80c41967c74998206511723a67 Mon Sep 17 00:00:00 2001 From: Jimmy Leung <43258070+hkleungai@users.noreply.github.com> Date: Tue, 18 Nov 2025 05:25:06 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74083=20feat(v?= =?UTF-8?q?alidator):=20add=20overload=20to=20isLength(),=20enforce=20disc?= =?UTF-8?q?reteLengths=20to=20be=20array=20by=20@hkleungai?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/validator/index.d.ts | 5 +++-- types/validator/validator-tests.ts | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/types/validator/index.d.ts b/types/validator/index.d.ts index 4a1d991a33b857..1537d47b062960 100644 --- a/types/validator/index.d.ts +++ b/types/validator/index.d.ts @@ -883,7 +883,7 @@ declare namespace validator { /** * @default undefined */ - discreteLengths?: number | Array | undefined; + discreteLengths?: Array | undefined; } /** @@ -893,7 +893,8 @@ declare namespace validator { * * @param [options] - Options */ - export function isLength(str: string, options?: IsLengthOptions): boolean; + export function isLength(str: string, minOrOptions?: number | IsLengthOptions): boolean; + export function isLength(str: string, min: number, max: number): boolean; export type LicensePlateLocale = | "cs-CZ" diff --git a/types/validator/validator-tests.ts b/types/validator/validator-tests.ts index f1d2db4e293526..b8abfbde79a22d 100644 --- a/types/validator/validator-tests.ts +++ b/types/validator/validator-tests.ts @@ -61,7 +61,7 @@ import isISSNFunc from "validator/lib/isISSN"; import isJSONFunc, { IsJSONOptions } from "validator/lib/isJSON"; import isJWTFunc from "validator/lib/isJWT"; import isLatLongFunc, { IsLatLongOptions } from "validator/lib/isLatLong"; -import isLengthFunc from "validator/lib/isLength"; +import isLengthFunc, { IsLengthOptions } from "validator/lib/isLength"; import isLicensePlateFunc from "validator/lib/isLicensePlate"; import isLocaleFunc from "validator/lib/isLocale"; import isLowercaseFunc from "validator/lib/isLowercase"; @@ -471,7 +471,7 @@ import isISSNFuncEs from "validator/es/lib/isISSN"; import isJSONFuncEs, { IsJSONOptions as IsJSONOptionsEs } from "validator/es/lib/isJSON"; import isJWTFuncEs from "validator/es/lib/isJWT"; import isLatLongFuncEs, { IsLatLongOptions as IsLatLongOptionsEs } from "validator/es/lib/isLatLong"; -import isLengthFuncEs from "validator/es/lib/isLength"; +import isLengthFuncEs, { IsLengthOptions as IsLengthOptionsEs } from "validator/es/lib/isLength"; import isLicensePlateFuncEs from "validator/es/lib/isLicensePlate"; import isLocaleFuncEs from "validator/es/lib/isLocale"; import isLowercaseFuncEs from "validator/es/lib/isLowercase"; @@ -1008,9 +1008,17 @@ const any: any = null; result = validator.isLatLong("sample", {}); result = validator.isLatLong("sample", { checkDMS: true } satisfies IsLatLongOptions); - const isLengthOptions: validator.IsLengthOptions = {}; - result = validator.isLength("sample", isLengthOptions); result = validator.isLength("sample"); + result = validator.isLength("sample", {}); + result = validator.isLength("sample", { min: 0, max: 3, discreteLengths: [1, 2] } satisfies IsLengthOptions); + result = validator.isLength("sample", 0); + result = validator.isLength("sample", 0, 3); + // Both overloads happen to allow using exactly two argument, [str, number] & [str, object] + // Hence if 2nd arg is of union type `number | object`, typechecking can pass. + result = validator.isLength("sample", result ? 0 : { min: 0, max: 3 }); + // @ts-expect-error + // Using 3rd arg here is problematic, without first ensuring that the 2nd argument is a number. + result = validator.isLength("sample", result ? 0 : { min: 0, max: 3 }, 3); result = validator.isLicensePlate("sample", "cs-CZ" satisfies validator.LicensePlateLocale); result = validator.isLicensePlate("sample", "de-DE"); From 26410a3128edfa5428af300f82b4b522743b9287 Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:08:53 +0100 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74086=20[chrom?= =?UTF-8?q?e]=20clean=20tests=20and=20enable=20no-empty-interface=20eslint?= =?UTF-8?q?=20rule=20by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/.eslintrc.json | 3 +- types/chrome/index.d.ts | 5 + types/chrome/test/index.ts | 177 +++++++++++++++--------------------- 3 files changed, 79 insertions(+), 106 deletions(-) diff --git a/types/chrome/.eslintrc.json b/types/chrome/.eslintrc.json index c00b46a09e7150..d9318311cc504c 100644 --- a/types/chrome/.eslintrc.json +++ b/types/chrome/.eslintrc.json @@ -1,7 +1,6 @@ { "rules": { "@definitelytyped/no-unnecessary-generics": "off", - "@definitelytyped/strict-export-declare-modifiers": "off", - "@typescript-eslint/no-empty-interface": "off" + "@definitelytyped/strict-export-declare-modifiers": "off" } } diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index e50f00a491d749..e88d8e2b8ea758 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -2524,6 +2524,7 @@ declare namespace chrome { } /** Declarative event action that redirects a network request to an empty document. */ + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface RedirectToEmptyDocument {} /** Declarative event action that redirects a network request. */ @@ -2566,6 +2567,7 @@ declare namespace chrome { } /** Declarative event action that cancels a network request. */ + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CancelRequest {} /** Removes the request header of the specified name. Do not use SetRequestHeader and RemoveRequestHeader with the same header name on the same request. Each request header name occurs only once in each request. */ @@ -2633,6 +2635,7 @@ declare namespace chrome { } /** Declarative event action that redirects a network request to a transparent image. */ + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface RedirectToTransparentImage {} /** Adds a cookie to the request or overrides a cookie, in case another cookie of the same name exists already. Note that it is preferred to use the Cookies API because this is computationally less expensive. */ @@ -10199,6 +10202,7 @@ declare namespace chrome { } /** @deprecated Use {@link CpuTime} instead. */ + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ProcessorUsage extends CpuTime {} export interface ProcessorInfo { @@ -12423,6 +12427,7 @@ declare namespace chrome { } /** @deprecated Use {@link Parameters} instead */ + // eslint-disable-next-line @typescript-eslint/no-empty-interface interface VpnSessionParameters extends Parameters {} /** The enum is used by the platform to notify the client of the VPN session status. */ diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index cfa02584508798..be920025779dd3 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -63,7 +63,7 @@ function testBookmarks() { chrome.bookmarks.get("1", () => {}).then(() => {}); chrome.bookmarks.getChildren("1"); // $ExpectType Promise - chrome.bookmarks.getChildren("1", ([result]) => checkBookmarkTreeNodeResult(result)); // $ExpectType void); + chrome.bookmarks.getChildren("1", ([result]) => checkBookmarkTreeNodeResult(result)); // $ExpectType void // @ts-expect-error chrome.bookmarks.getChildren("1", () => {}).then(() => {}); @@ -93,12 +93,12 @@ function testBookmarks() { chrome.bookmarks.move("1", destination, () => {}).then(() => {}); chrome.bookmarks.remove("1"); // $ExpectType Promise - chrome.bookmarks.remove("1", () => void 0); + chrome.bookmarks.remove("1", () => void 0); // $ExpectType void // @ts-expect-error chrome.bookmarks.remove("1", () => {}).then(() => {}); chrome.bookmarks.removeTree("1"); // $ExpectType Promise - chrome.bookmarks.removeTree("1", () => void 0); + chrome.bookmarks.removeTree("1", () => void 0); // $ExpectType void // @ts-expect-error chrome.bookmarks.removeTree("1", () => {}).then(() => {}); @@ -225,7 +225,7 @@ function testWebNavigation() { chrome.webNavigation.getFrame(getFrameDetails); // $ExpectType Promise chrome.webNavigation.getFrame(getFrameDetails2); // $ExpectType Promise - chrome.webNavigation.getFrame(getFrameDetails, (frame) => { // $ExpectType void; + chrome.webNavigation.getFrame(getFrameDetails, (frame) => { // $ExpectType void frame; // $ExpectType GetFrameResultDetails | null }); chrome.webNavigation.getFrame(getFrameDetails2, (frame) => { // $ExpectType void @@ -402,7 +402,7 @@ function testProxy() { } // https://developer.chrome.com/docs/extensions/reference/api/notifications -function testNotification() { +function testNotifications() { chrome.notifications.PermissionLevel.DENIED === "denied"; chrome.notifications.PermissionLevel.GRANTED === "granted"; @@ -1298,7 +1298,7 @@ function testDeclarativeContent() { }, }; - const condition = new chrome.declarativeContent.PageStateMatcher(pageStateMatcherProperties); // ExpectType PageStateMatcher + const condition = new chrome.declarativeContent.PageStateMatcher(pageStateMatcherProperties); // $ExpectType PageStateMatcher const requestContentScriptProperties: chrome.declarativeContent.RequestContentScriptProperties = { allFrames: true, @@ -1307,15 +1307,15 @@ function testDeclarativeContent() { matchAboutBlank: true, }; - new chrome.declarativeContent.RequestContentScript(requestContentScriptProperties); // ExpectType RequestContentScript + new chrome.declarativeContent.RequestContentScript(requestContentScriptProperties); // $ExpectType RequestContentScript const imageData = new ImageData(32, 32); - new chrome.declarativeContent.SetIcon({ imageData }); // ExpectType SetIcon + new chrome.declarativeContent.SetIcon({ imageData }); // $ExpectType SetIcon - const action = new chrome.declarativeContent.ShowAction(); // ExpectType ShowAction + const action = new chrome.declarativeContent.ShowAction(); // $ExpectType ShowAction - new chrome.declarativeContent.ShowPageAction(); // ExpectType ShowPageAction + new chrome.declarativeContent.ShowPageAction(); // $ExpectType ShowPageAction const rule: chrome.events.Rule = { conditions: [condition], @@ -1343,7 +1343,7 @@ function testDeclarativeContent() { chrome.declarativeContent.onPageChanged.removeRules(["identifier"], () => void 0); // $ExpectType void } -// https://developer.chrome.com/extensions/storage#type-StorageArea +// https://developer.chrome.com/docs/extensions/reference/api/storage function testStorage() { chrome.storage.AccessLevel.TRUSTED_AND_UNTRUSTED_CONTEXTS === "TRUSTED_AND_UNTRUSTED_CONTEXTS"; chrome.storage.AccessLevel.TRUSTED_CONTEXTS === "TRUSTED_CONTEXTS"; @@ -1507,7 +1507,7 @@ function testStorage() { }); } -// https://developer.chrome.com/docs/extensions/reference/api/tss +// https://developer.chrome.com/docs/extensions/reference/api/tts function testTts() { chrome.tts.EventType.CANCELLED === "cancelled"; chrome.tts.EventType.END === "end"; @@ -1800,24 +1800,24 @@ function testDevtoolsInspectedWindow() { chrome.devtools.inspectedWindow.eval(expression); // $ExpectType void chrome.devtools.inspectedWindow.eval(expression, evalOptions); // $ExpectType void chrome.devtools.inspectedWindow.eval(expression, evalOptions, (result, exceptionInfo) => { // $ExpectType void - result; // ExpectType object + result; // $ExpectType { [key: string]: unknown; } - exceptionInfo.code; // ExpectType string - exceptionInfo.description; // ExpectType string - exceptionInfo.details; // ExpectType unknown[] - exceptionInfo.isError; // ExpectType boolean - exceptionInfo.isException; // ExpectType boolean - exceptionInfo.value; // ExpectType string + exceptionInfo.code; // $ExpectType string + exceptionInfo.description; // $ExpectType string + exceptionInfo.details; // $ExpectType any[] + exceptionInfo.isError; // $ExpectType boolean + exceptionInfo.isException; // $ExpectType boolean + exceptionInfo.value; // $ExpectType string }); chrome.devtools.inspectedWindow.eval(expression, (result) => { // $ExpectType void - result; // ExpectType object + result; // $ExpectType { [key: string]: unknown; } }); chrome.devtools.inspectedWindow.eval<{ title: string }>(expression, evalOptions, (result) => { // $ExpectType void - result.title; // ExpectType string + result.title; // $ExpectType string }); chrome.devtools.inspectedWindow.getResources((resources) => { // $ExpectType void - resources; // ExpectType Resource[] + resources; // $ExpectType Resource[] }); const reloadOptions: chrome.devtools.inspectedWindow.ReloadOptions = { @@ -1830,12 +1830,12 @@ function testDevtoolsInspectedWindow() { chrome.devtools.inspectedWindow.reload(reloadOptions); // $ExpectType void checkChromeEvent(chrome.devtools.inspectedWindow.onResourceAdded, (resource) => { - resource; // ExpectType Resource + resource; // $ExpectType Resource }); checkChromeEvent(chrome.devtools.inspectedWindow.onResourceContentCommitted, (resource, content) => { - resource; // ExpectType Resource - content; // ExpectType string + resource; // $ExpectType Resource + content; // $ExpectType string }); } @@ -1847,7 +1847,7 @@ function testDevtoolsPerformance() { // https://developer.chrome.com/docs/extensions/reference/api/devtools/network function testDevtoolsNetwork() { - chrome.devtools.network.getHAR((harLog) => { + chrome.devtools.network.getHAR((harLog) => { // $ExpectType void harLog; // $ExpectType Log }); @@ -2426,7 +2426,7 @@ async function testAction() { chrome.action.isEnabled((isEnabled) => { // $ExpectType void isEnabled; // $ExpectType boolean }); - chrome.action.isEnabled(tabId, (isEnabled) => { + chrome.action.isEnabled(tabId, (isEnabled) => { // $ExpectType void isEnabled; // $ExpectType boolean }); // @ts-expect-error @@ -2618,25 +2618,8 @@ function testAudio() { }); } -// https://developer.chrome.com/docs/extensions/reference/bookmarks -async function testBookmarksForPromise() { - await chrome.bookmarks.search("query1"); - await chrome.bookmarks.search({}); - await chrome.bookmarks.getTree(); - await chrome.bookmarks.getRecent(0); - await chrome.bookmarks.get("id1"); - await chrome.bookmarks.get(["id1"]); - await chrome.bookmarks.create({}); - await chrome.bookmarks.move("id1", {}); - await chrome.bookmarks.update("id1", {}); - await chrome.bookmarks.remove("id1"); - await chrome.bookmarks.getChildren("id1"); - await chrome.bookmarks.getSubTree("id1"); - await chrome.bookmarks.removeTree("id1"); -} - // https://developer.chrome.com/docs/extensions/reference/api/cookies -async function testCookie() { +async function testCookies() { chrome.cookies.OnChangedCause.EVICTED === "evicted"; chrome.cookies.OnChangedCause.EXPIRED === "expired"; chrome.cookies.OnChangedCause.EXPIRED_OVERWRITE === "expired_overwrite"; @@ -2659,7 +2642,7 @@ async function testCookie() { }; chrome.cookies.get(cookieDetails); // $ExpectType Promise - chrome.cookies.get(cookieDetails, (cookie) => { + chrome.cookies.get(cookieDetails, (cookie) => { // $ExpectType void cookie; // $ExpectType Cookie | null }); // @ts-expect-error @@ -2680,14 +2663,14 @@ async function testCookie() { }; chrome.cookies.getAll(cookiesAllDetails); // $ExpectType Promise - chrome.cookies.getAll(cookiesAllDetails, (cookies) => { + chrome.cookies.getAll(cookiesAllDetails, (cookies) => { // $ExpectType void cookies; // $ExpectType Cookie[] }); // @ts-expect-error chrome.cookies.getAll(cookiesAllDetails, () => {}).then(() => {}); chrome.cookies.getAllCookieStores(); // $ExpectType Promise - chrome.cookies.getAllCookieStores((cookieStores) => { + chrome.cookies.getAllCookieStores((cookieStores) => { // $ExpectType void cookieStores; // $ExpectType CookieStore[] }); // @ts-expect-error @@ -2698,14 +2681,14 @@ async function testCookie() { }; chrome.cookies.getPartitionKey(frameDetails); // $ExpectType Promise<{ partitionKey: CookiePartitionKey }> - chrome.cookies.getPartitionKey(frameDetails, ({ partitionKey }) => { + chrome.cookies.getPartitionKey(frameDetails, ({ partitionKey }) => { // $ExpectType void partitionKey; // $ExpectType CookiePartitionKey }); // @ts-expect-error chrome.cookies.getPartitionKey(frameDetails, () => {}).then(() => {}); chrome.cookies.remove(cookieDetails); // $ExpectType Promise - chrome.cookies.remove(cookieDetails, (details) => { + chrome.cookies.remove(cookieDetails, (details) => { // $ExpectType void details; // $ExpectType CookieDetails }); // @ts-expect-error @@ -2728,7 +2711,7 @@ async function testCookie() { }; chrome.cookies.set(cookieDetailsSet); // $ExpectType Promise - chrome.cookies.set(cookieDetailsSet, (cookie) => { + chrome.cookies.set(cookieDetailsSet, (cookie) => { // $ExpectType void cookie; // $ExpectType Cookie | null }); // @ts-expect-error @@ -3272,7 +3255,7 @@ async function testTabs() { chrome.tabs.captureVisibleTab(windowId); // $ExpectType Promise chrome.tabs.captureVisibleTab(windowCaptureOptions); // $ExpectType Promise chrome.tabs.captureVisibleTab(windowId, windowCaptureOptions); // $ExpectType Promise - chrome.tabs.captureVisibleTab((dataUrl) => { + chrome.tabs.captureVisibleTab((dataUrl) => { // $ExpectType void dataUrl; // $ExpectType string }); chrome.tabs.captureVisibleTab(windowId, (dataUrl) => { // $ExpectType void @@ -3319,7 +3302,7 @@ async function testTabs() { chrome.tabs.detectLanguage((language) => { // $ExpectType void language; // $ExpectType string }); - chrome.tabs.detectLanguage(tabId, (language) => { + chrome.tabs.detectLanguage(tabId, (language) => { // $ExpectType void language; // $ExpectType string }); // @ts-expect-error @@ -3337,7 +3320,7 @@ async function testTabs() { chrome.tabs.discard(() => {}).then(() => {}); chrome.tabs.duplicate(tabId); // $ExpectType Promise - chrome.tabs.duplicate(tabId, (tab) => { + chrome.tabs.duplicate(tabId, (tab) => { // $ExpectType void tab; // $ExpectType Tab | undefined }); // @ts-expect-error @@ -3430,7 +3413,7 @@ async function testTabs() { chrome.tabs.move(tabId, moveProperties, (tab) => { // $ExpectType void tab; // $ExpectType Tab }); - chrome.tabs.move([tabId], moveProperties, (tabs) => { + chrome.tabs.move([tabId], moveProperties, (tabs) => { // $ExpectType void tabs; // $ExpectType Tab[] }); // @ts-expect-error @@ -3710,7 +3693,7 @@ async function testTabs() { } // https://developer.chrome.com/docs/extensions/reference/api/tabGroups -async function testTabGroup() { +async function testTabGroups() { chrome.tabGroups.Color.BLUE === "blue"; chrome.tabGroups.Color.CYAN === "cyan"; chrome.tabGroups.Color.GREEN === "green"; @@ -4820,7 +4803,7 @@ async function testCommands() { // https://developer.chrome.com/docs/extensions/reference/api/i18n function testI18n() { const text = "text"; - chrome.i18n.detectLanguage(text); // ExpectType Promise + chrome.i18n.detectLanguage(text); // $ExpectType Promise chrome.i18n.detectLanguage(text, (result) => { // $ExpectType void result.isReliable; // $ExpectType boolean result.languages[0].language; // $ExpectType string @@ -5191,31 +5174,16 @@ function testDownloads() { }); } -// https://developer.chrome.com/docs/extensions/reference/downloads -async function testDownloadsForPromise() { - await chrome.downloads.search({}); - await chrome.downloads.pause(1); - await chrome.downloads.getFileIcon(1); - await chrome.downloads.getFileIcon(1, {}); - await chrome.downloads.resume(1); - await chrome.downloads.cancel(1); - await chrome.downloads.download({ url: "https://example.com" }); - await chrome.downloads.erase({}); - await chrome.downloads.removeFile(1); - await chrome.downloads.acceptDanger(1); - await chrome.downloads.setUiOptions({ enabled: true }); -} - // https://developer.chrome.com/docs/extensions/reference/api/extension function testExtension() { chrome.extension.ViewType.POPUP === "popup"; chrome.extension.ViewType.TAB === "tab"; - chrome.extension.inIncognitoContext; // ExpectType boolean + chrome.extension.inIncognitoContext; // $ExpectType boolean - chrome.extension.lastError; // ExpectType chrome.runtime.LastError + chrome.extension.lastError; // $ExpectType LastError | undefined - chrome.extension.getBackgroundPage(); // ExpectType Window | null + chrome.extension.getBackgroundPage(); // $ExpectType Window | null const fetchProperties: chrome.extension.FetchProperties = { tabId: 1, @@ -5223,57 +5191,57 @@ function testExtension() { windowId: 1, }; - chrome.extension.getViews(fetchProperties); // ExpectType Window[] + chrome.extension.getViews(fetchProperties); // $ExpectType Window[] - chrome.extension.isAllowedFileSchemeAccess(); // ExpectType Promise - chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => { // ExpectType void - isAllowedAccess; // ExpectType boolean + chrome.extension.isAllowedFileSchemeAccess(); // $ExpectType Promise + chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => { // $ExpectType void + isAllowedAccess; // $ExpectType boolean }); // @ts-expect-error chrome.extension.isAllowedFileSchemeAccess(() => {}).then(() => {}); - chrome.extension.isAllowedIncognitoAccess(); // ExpectType Promise - chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => { // ExpectType void - isAllowedAccess; // ExpectType boolean + chrome.extension.isAllowedIncognitoAccess(); // $ExpectType Promise + chrome.extension.isAllowedIncognitoAccess((isAllowedAccess) => { // $ExpectType void + isAllowedAccess; // $ExpectType boolean }); // @ts-expect-error chrome.extension.isAllowedIncognitoAccess(() => {}).then(() => {}); - chrome.extension.setUpdateUrlData("data"); // ExpectType void + chrome.extension.setUpdateUrlData("data"); // $ExpectType void - chrome.extension.getExtensionTabs(); // ExpectType Window[] - chrome.extension.getExtensionTabs(1); // ExpectType Window[] + chrome.extension.getExtensionTabs(); // $ExpectType Window[] + chrome.extension.getExtensionTabs(1); // $ExpectType Window[] - chrome.extension.getURL("/path"); // ExpectType string + chrome.extension.getURL("/path"); // $ExpectType string const extensionId = "dummy-id"; const request = {}; - chrome.extension.sendRequest(request); // ExpectType void - chrome.extension.sendRequest(request, (response) => { // ExpectType void - response; // ExpectType any + chrome.extension.sendRequest(request); // $ExpectType void + chrome.extension.sendRequest(request, (response) => { // $ExpectType void + response; // $ExpectType any }); - chrome.extension.sendRequest(extensionId, request); // ExpectType void - chrome.extension.sendRequest(extensionId, request, (response) => { // ExpectType void - response; // ExpectType any + chrome.extension.sendRequest(extensionId, request); // $ExpectType void + chrome.extension.sendRequest(extensionId, request, (response) => { // $ExpectType void + response; // $ExpectType any }); - chrome.extension.sendRequest(1, (response) => { - response; // ExpectType boolean + chrome.extension.sendRequest(1, (response) => { // $ExpectType void + response; // $ExpectType boolean }); - chrome.extension.sendRequest(extensionId, 1, (response) => { - response; // ExpectType boolean + chrome.extension.sendRequest(extensionId, 1, (response) => { // $ExpectType void + response; // $ExpectType boolean }); checkChromeEvent(chrome.extension.onRequest, (request, sender, sendResponse) => { - request; // ExpectType any - sender; // ExpectType chrome.extension.MessageSender - sendResponse({}); // ExpectType void + request; // $ExpectType any + sender; // $ExpectType MessageSender + sendResponse({}); // $ExpectType void }); checkChromeEvent(chrome.extension.onRequestExternal, (request, sender, sendResponse) => { - request; // ExpectType any - sender; // ExpectType chrome.extension.MessageSender - sendResponse({}); // ExpectType void + request; // $ExpectType any + sender; // $ExpectType MessageSender + sendResponse({}); // $ExpectType void }); } @@ -6498,7 +6466,7 @@ function testUserScripts() { } // https://developer.chrome.com/docs/extensions/reference/api/enterprise/platformKeys -function testEnterPrisePlatformKeys() { +function testEnterprisePlatformKeys() { const tokenId = "tokenId"; chrome.enterprise.platformKeys.Scope.MACHINE === "MACHINE"; @@ -6734,6 +6702,7 @@ function testPrinting() { }); } +// https://developer.chrome.com/docs/extensions/reference/api/printingMetrics function testPrintingMetrics() { chrome.printingMetrics.ColorMode.BLACK_AND_WHITE === "BLACK_AND_WHITE"; chrome.printingMetrics.ColorMode.COLOR === "COLOR"; @@ -8082,7 +8051,7 @@ function testDesktopCapture() { }; chrome.desktopCapture.chooseDesktopMedia(sources, () => {}); // $ExpectType number - chrome.desktopCapture.chooseDesktopMedia(sources, tab, (streamId, options) => { + chrome.desktopCapture.chooseDesktopMedia(sources, tab, (streamId, options) => { // $ExpectType number streamId; // $ExpectType string options; // $ExpectType StreamOptions }); From 3705b3614169fd3c482f9a393f09dcc5604b962e Mon Sep 17 00:00:00 2001 From: Erwan Jugand <47392755+erwanjugand@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:09:32 +0100 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#74091=20[chrom?= =?UTF-8?q?e]=20update=20devtools.panels=20and=20downloads=20namespaces=20?= =?UTF-8?q?by=20@erwanjugand?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/chrome/index.d.ts | 17 ++++++++++++++++- types/chrome/test/index.ts | 12 +++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/types/chrome/index.d.ts b/types/chrome/index.d.ts index e88d8e2b8ea758..f03401d0d3491d 100644 --- a/types/chrome/index.d.ts +++ b/types/chrome/index.d.ts @@ -3018,6 +3018,12 @@ declare namespace chrome { onHidden: events.Event<() => void>; } + /** + * Theme used by DevTools. + * @since Chrome 99 + */ + export type Theme = "default" | "dark"; + /** Elements panel. */ export const elements: ElementsPanel; @@ -3050,6 +3056,12 @@ declare namespace chrome { ) => void, ): void; + /** + * Specifies the function to be called when the current theme changes in DevTools. To unset the handler, either call the method with no parameters or pass `null` as the parameter. + * @since Chrome 99 + */ + export function setThemeChangeHandler(callback?: (theme: Theme) => void): void; + /** * Requests DevTools to open a URL in a Developer Tools panel. * @param url The URL of the resource to open. @@ -3068,7 +3080,7 @@ declare namespace chrome { * The name of the color theme set in user's DevTools settings. * @since Chrome 59 */ - export const themeName: "default" | "dark"; + export const themeName: Theme; } //////////////////// @@ -3746,6 +3758,7 @@ declare namespace chrome { SAFE = "safe", /** The user has accepted the dangerous download. */ ACCEPTED = "accepted", + /** Enterprise-related values. */ ALLOWLISTED_BY_POLICY = "allowlistedByPolicy", ASYNC_SCANNING = "asyncScanning", ASYNC_LOCAL_PASSWORD_SCANNING = "asyncLocalPasswordScanning", @@ -3760,6 +3773,8 @@ declare namespace chrome { PROMPT_FOR_LOCAL_PASSWORD_SCANNING = "promptForLocalPasswordScanning", ACCOUNT_COMPROMISE = "accountCompromise", BLOCKED_SCAN_FAILED = "blockedScanFailed", + /** For use by the Secure Enterprise Browser extension. When required, Chrome will block the download to disc and download the file directly to Google Drive. */ + FORCE_SAVE_TO_GDRIVE = "forceSaveToGdrive", } export interface DownloadItem { diff --git a/types/chrome/test/index.ts b/types/chrome/test/index.ts index be920025779dd3..71b46b56a3ab8e 100644 --- a/types/chrome/test/index.ts +++ b/types/chrome/test/index.ts @@ -1760,7 +1760,7 @@ function testDevtoolsPanels() { }); checkChromeEvent(chrome.devtools.panels.sources.onSelectionChanged, () => void 0); - chrome.devtools.panels.themeName; // $ExpectType "default" | "dark" + chrome.devtools.panels.themeName; // $ExpectType Theme chrome.devtools.panels.create(title, iconPath, pagePath); // $ExpectType void chrome.devtools.panels.create(title, iconPath, pagePath, panel => { // $ExpectType void @@ -1785,6 +1785,11 @@ function testDevtoolsPanels() { resource; // $ExpectType Resource lineNumber; // $ExpectType number }); + + chrome.devtools.panels.setThemeChangeHandler(); // $ExpectType void + chrome.devtools.panels.setThemeChangeHandler((theme) => { // $ExpectType void + theme; // $ExpectType Theme + }); } // https://developer.chrome.com/docs/extensions/reference/api/devtools/inspectedWindow @@ -4922,6 +4927,7 @@ function testDownloads() { chrome.downloads.DangerType.DEEP_SCANNED_OPENED_DANGEROUS === "deepScannedOpenedDangerous"; chrome.downloads.DangerType.DEEP_SCANNED_SAFE === "deepScannedSafe"; chrome.downloads.DangerType.FILE === "file"; + chrome.downloads.DangerType.FORCE_SAVE_TO_GDRIVE === "forceSaveToGdrive"; chrome.downloads.DangerType.HOST === "host"; chrome.downloads.DangerType.PASSWORD_PROTECTED === "passwordProtected"; chrome.downloads.DangerType.PROMPT_FOR_LOCAL_PASSWORD_SCANNING === "promptForLocalPasswordScanning"; @@ -5082,7 +5088,7 @@ function testDownloads() { result.byExtensionName; // $ExpectType string | undefined result.bytesReceived; // $ExpectType number result.canResume; // $ExpectType boolean - result.danger; // $ExpectType "file" | "url" | "content" | "uncommon" | "host" | "unwanted" | "safe" | "accepted" | "allowlistedByPolicy" | "asyncScanning" | "asyncLocalPasswordScanning" | "passwordProtected" | "blockedTooLarge" | "sensitiveContentWarning" | "sensitiveContentBlock" | "deepScannedFailed" | "deepScannedSafe" | "deepScannedOpenedDangerous" | "promptForScanning" | "promptForLocalPasswordScanning" | "accountCompromise" | "blockedScanFailed" + result.danger; // $ExpectType "file" | "url" | "content" | "uncommon" | "host" | "unwanted" | "safe" | "accepted" | "allowlistedByPolicy" | "asyncScanning" | "asyncLocalPasswordScanning" | "passwordProtected" | "blockedTooLarge" | "sensitiveContentWarning" | "sensitiveContentBlock" | "deepScannedFailed" | "deepScannedSafe" | "deepScannedOpenedDangerous" | "promptForScanning" | "promptForLocalPasswordScanning" | "accountCompromise" | "blockedScanFailed" | "forceSaveToGdrive" result.endTime; // $ExpectType string | undefined result.error; // $ExpectType "CRASH" | "FILE_ACCESS_DENIED" | "FILE_BLOCKED" | "FILE_FAILED" | "FILE_HASH_MISMATCH" | "FILE_NAME_TOO_LONG" | "FILE_NO_SPACE" | "FILE_SAME_AS_SOURCE" | "FILE_SECURITY_CHECK_FAILED" | "FILE_TOO_LARGE" | "FILE_TOO_SHORT" | "FILE_TRANSIENT_ERROR" | "FILE_VIRUS_INFECTED" | "NETWORK_DISCONNECTED" | "NETWORK_FAILED" | "NETWORK_INVALID_REQUEST" | "NETWORK_SERVER_DOWN" | "NETWORK_TIMEOUT" | "SERVER_BAD_CONTENT" | "SERVER_CERT_PROBLEM" | "SERVER_CONTENT_LENGTH_MISMATCH" | "SERVER_CROSS_ORIGIN_REDIRECT" | "SERVER_FAILED" | "SERVER_FORBIDDEN" | "SERVER_NO_RANGE" | "SERVER_UNAUTHORIZED" | "SERVER_UNREACHABLE" | "USER_CANCELED" | "USER_SHUTDOWN" | undefined result.estimatedEndTime; // $ExpectType string | undefined @@ -5140,7 +5146,7 @@ function testDownloads() { downloadItem.byExtensionName; // $ExpectType string | undefined downloadItem.bytesReceived; // $ExpectType number downloadItem.canResume; // $ExpectType boolean - downloadItem.danger; // $ExpectType "file" | "url" | "content" | "uncommon" | "host" | "unwanted" | "safe" | "accepted" | "allowlistedByPolicy" | "asyncScanning" | "asyncLocalPasswordScanning" | "passwordProtected" | "blockedTooLarge" | "sensitiveContentWarning" | "sensitiveContentBlock" | "deepScannedFailed" | "deepScannedSafe" | "deepScannedOpenedDangerous" | "promptForScanning" | "promptForLocalPasswordScanning" | "accountCompromise" | "blockedScanFailed" + downloadItem.danger; // $ExpectType "file" | "url" | "content" | "uncommon" | "host" | "unwanted" | "safe" | "accepted" | "allowlistedByPolicy" | "asyncScanning" | "asyncLocalPasswordScanning" | "passwordProtected" | "blockedTooLarge" | "sensitiveContentWarning" | "sensitiveContentBlock" | "deepScannedFailed" | "deepScannedSafe" | "deepScannedOpenedDangerous" | "promptForScanning" | "promptForLocalPasswordScanning" | "accountCompromise" | "blockedScanFailed" | "forceSaveToGdrive" downloadItem.endTime; // $ExpectType string | undefined downloadItem.error; // $ExpectType "CRASH" | "FILE_ACCESS_DENIED" | "FILE_BLOCKED" | "FILE_FAILED" | "FILE_HASH_MISMATCH" | "FILE_NAME_TOO_LONG" | "FILE_NO_SPACE" | "FILE_SAME_AS_SOURCE" | "FILE_SECURITY_CHECK_FAILED" | "FILE_TOO_LARGE" | "FILE_TOO_SHORT" | "FILE_TRANSIENT_ERROR" | "FILE_VIRUS_INFECTED" | "NETWORK_DISCONNECTED" | "NETWORK_FAILED" | "NETWORK_INVALID_REQUEST" | "NETWORK_SERVER_DOWN" | "NETWORK_TIMEOUT" | "SERVER_BAD_CONTENT" | "SERVER_CERT_PROBLEM" | "SERVER_CONTENT_LENGTH_MISMATCH" | "SERVER_CROSS_ORIGIN_REDIRECT" | "SERVER_FAILED" | "SERVER_FORBIDDEN" | "SERVER_NO_RANGE" | "SERVER_UNAUTHORIZED" | "SERVER_UNREACHABLE" | "USER_CANCELED" | "USER_SHUTDOWN" | undefined downloadItem.estimatedEndTime; // $ExpectType string | undefined