diff --git a/types/react-dom/canary.d.ts b/types/react-dom/canary.d.ts index 964d0df7ad2505..8d5d0fc2ab1284 100644 --- a/types/react-dom/canary.d.ts +++ b/types/react-dom/canary.d.ts @@ -32,21 +32,78 @@ import ReactDOM = require("."); export {}; declare module "." { - type PreloadAs = "font" | "script" | "style"; + function prefetchDNS(href: string): void; + + interface PreconnectOptions { + // Don't create a helper type. + // It would have to be in module scope to be inlined in TS tooltips. + // But then it becomes part of the public API. + // TODO: Upstream to microsoft/TypeScript-DOM-lib-generator -> w3c/webref + // since the spec has a notion of a dedicated type: https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attribute + crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; + } + function preconnect(href: string, options?: PreconnectOptions): void; + + type PreloadAs = + | "audio" + | "document" + | "embed" + | "fetch" + | "font" + | "image" + | "object" + | "track" + | "script" + | "style" + | "video" + | "worker"; interface PreloadOptions { as: PreloadAs; - crossOrigin?: string | undefined; + crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; + fetchPriority?: "high" | "low" | "auto" | undefined; + // TODO: These should only be allowed with `as: 'image'` but it's not trivial to write tests against the full TS support matrix. + imageSizes?: string | undefined; + imageSrcSet?: string | undefined; integrity?: string | undefined; + nonce?: string | undefined; + referrerPolicy?: ReferrerPolicy | undefined; } function preload(href: string, options?: PreloadOptions): void; + // https://html.spec.whatwg.org/multipage/links.html#link-type-modulepreload + type PreloadModuleAs = RequestDestination; + interface PreloadModuleOptions { + /** + * @default "script" + */ + as: PreloadModuleAs; + crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; + integrity?: string | undefined; + nonce?: string | undefined; + } + function preloadModule(href: string, options?: PreloadModuleOptions): void; + type PreinitAs = "script" | "style"; interface PreinitOptions { as: PreinitAs; - crossOrigin?: string | undefined; + crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; + fetchPriority?: "high" | "low" | "auto" | undefined; precedence?: string | undefined; integrity?: string | undefined; nonce?: string | undefined; } function preinit(href: string, options?: PreinitOptions): void; + + // Will be expanded to include all of https://github.com/tc39/proposal-import-attributes + type PreinitModuleAs = "script"; + interface PreinitModuleOptions { + /** + * @default "script" + */ + as?: PreinitModuleAs; + crossOrigin?: "anonymous" | "use-credentials" | "" | undefined; + integrity?: string | undefined; + nonce?: string | undefined; + } + function preinitModule(href: string, options?: PreinitModuleOptions): void; } diff --git a/types/react-dom/test/canary-tests.tsx b/types/react-dom/test/canary-tests.tsx index c67964be40190a..eedae1583a205e 100644 --- a/types/react-dom/test/canary-tests.tsx +++ b/types/react-dom/test/canary-tests.tsx @@ -2,8 +2,12 @@ function preloadTest() { function Component() { - ReactDOM.preload("foo", { as: "style", integrity: "sad" }); - ReactDOM.preload("bar", { as: "font" }); + ReactDOM.preload("foo", { as: "style", fetchPriority: "high", integrity: "sad" }); + ReactDOM.preload("bar", { + as: "font", + // @ts-expect-error Unknown fetch priority + fetchPriority: "unknown", + }); ReactDOM.preload("baz", { as: "script", crossOrigin: "use-credentials" }); ReactDOM.preload("baz", { // @ts-expect-error @@ -11,15 +15,33 @@ function preloadTest() { }); ReactDOM.preload("bar", { as: "font", - // @ts-expect-error -- Only allowed in preinit nonce: "0xeac1", }); + ReactDOM.preload("foo", { + as: "image", + imageSrcSet: "fooset", + imageSizes: "foosizes", + referrerPolicy: "no-referrer", + }); + ReactDOM.preload("foo", { + as: "image", + // @ts-expect-error Not specified in https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + referrerPolicy: "unknown-policy", + }); + ReactDOM.preload("foo", { + as: "script", + // Undesired. Should not typecheck. + imageSrcSet: "fooset", + imageSizes: "foosizes", + }); ReactDOM.preinit("foo", { as: "style", crossOrigin: "anonymous", + fetchPriority: "high", precedence: "high", integrity: "sad", + nonce: "0xeac1", }); ReactDOM.preinit("bar", { // @ts-expect-error Only available in preload @@ -27,6 +49,8 @@ function preloadTest() { }); ReactDOM.preinit("baz", { as: "script", + // @ts-expect-error Unknown fetch priority + fetchPriority: "unknown", }); ReactDOM.preinit("baz", { // @ts-expect-error @@ -36,5 +60,42 @@ function preloadTest() { as: "script", nonce: "0xeac1", }); + + // @ts-expect-error + ReactDOM.preconnect(); + ReactDOM.preconnect("foo"); + ReactDOM.preconnect("bar", { crossOrigin: "anonymous" }); + + // @ts-expect-error + ReactDOM.prefetchDNS(); + ReactDOM.prefetchDNS("foo"); + ReactDOM.prefetchDNS( + "bar", // @ts-expect-error prefetchDNS does not accept any options at the moment + {}, + ); + + // @ts-expect-error + ReactDOM.preloadModule(); + ReactDOM.preloadModule("browserdefault"); + ReactDOM.preloadModule("browserdefault", { + as: "script", + crossOrigin: "use-credentials", + integrity: "0xeac1", + nonce: "secret", + }); + ReactDOM.preloadModule("worker", { as: "worker" }); + ReactDOM.preloadModule("worker", { + // @ts-expect-error Unknown request destination + as: "serviceworker", + }); + + // @ts-expect-error + ReactDOM.preinitModule(); + ReactDOM.preinitModule("browserdefault"); + ReactDOM.preinitModule("browserdefault", { as: "script", crossOrigin: "use-credentials", integrity: "0xeac1" }); + ReactDOM.preinitModule("data", { + // @ts-expect-error Not supported (yet) + as: "json", + }); } }