Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditionally add node/DOM types to StructuredCloneable #908

Merged

Conversation

thecodewarrior
Copy link
Contributor

While investigating #899, I discovered a solution that lets us only include DOM/Node types if they actually exist. Based on this code from the node type declarations, I came up with this solution:

/** Grab the specified type from its corresponding global constructor, if it's declared */
type ExtractFromGlobalConstructor<Name extends string> =
	typeof globalThis extends Record<Name, new (...args: any[]) => infer T> ? T : never

This only works with types that have a public constructor in globalThis, but Blob, File, and all the DOM types appear to have constructors and work like this. In order to verify that all the DOM types have public constructors I added @webgpu/types, @types/dom-webcodecs, and @types/webxr, which got me most of the types I was missing, then I created this file to manually check them:

type DOMKeys =
	| 'AudioData'
	| 'CropTarget'
	| 'CryptoKey'
	| 'DOMException'
	| 'DOMMatrix'
	| 'DOMMatrixReadOnly'
	| 'DOMPoint'
	| 'DOMPointReadOnly'
	| 'DOMQuad'
	| 'DOMRect'
	| 'DOMRectReadOnly'
	| 'FileList'
	| 'FileSystemDirectoryHandle'
	| 'FileSystemFileHandle'
	| 'FileSystemHandle'
	| 'GPUCompilationInfo'
	| 'GPUCompilationMessage'
	| 'ImageBitmap'
	| 'ImageData'
	| 'RTCCertificate'
	| 'VideoFrame'

/**
- `Name` = found global with valid constructor
- `~Name` = found global, but no constructor found
- `!Name` = global not found
*/
type FindGlobals<Name extends string> =
	Name extends string
		? typeof globalThis extends Record<Name, new (...args: any[]) => any> ? Name
			: typeof globalThis extends Record<Name, any> ? `~${Name}`
				: `!${Name}`
		: never;

import "@webgpu/types"

const found: FindGlobals<DOMKeys>[] = [
	'AudioData',
	'!CropTarget', // no typescript declarations exist for this yet
	'CryptoKey',
	'DOMException',
	'DOMMatrix',
	'DOMMatrixReadOnly',
	'DOMPoint',
	'DOMPointReadOnly',
	'DOMQuad',
	'DOMRect',
	'DOMRectReadOnly',
	'FileList',
	'FileSystemDirectoryHandle',
	'FileSystemFileHandle',
	'FileSystemHandle',
	'GPUCompilationInfo',
	'GPUCompilationMessage',
	'ImageBitmap',
	'ImageData',
	'RTCCertificate',
	'VideoFrame',
]

Fixes #899

@voxpelli
Copy link
Collaborator

Created a related PR, #912, that makes the type checks properly fail for the current scenario.

Would be good to get work on that in tandem with this.

I also think we should find a model where we test the types in contexts where eg. both the dom lib and @types/node is available, to ensure it works as expected in all supported context

source/find-global-type.d.ts Outdated Show resolved Hide resolved

Use-case: Conditionally referencing DOM types only when the DOM library present.

*Limitations:* Due to peculiarities with the behavior of `globalThis`, "globally defined" has a narrow definition in
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend opening a TypeScript issue about this limitation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The odd behavior itself is correct (microsoft/TypeScript#39504), so there's nothing to be done on that front. In terms of avoiding this hack in the first place, there's already an issue regarding that: microsoft/TypeScript#31894

@sindresorhus sindresorhus merged commit 0086cd6 into sindresorhus:main Jul 16, 2024
8 checks passed
@sindresorhus
Copy link
Owner

Thanks for contributing 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Web-specific version of StructuredCloneable type
4 participants