-
-
Notifications
You must be signed in to change notification settings - Fork 542
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Sindre Sorhus <[email protected]>
- Loading branch information
1 parent
3b1ceeb
commit 0086cd6
Showing
5 changed files
with
170 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
Tries to find the type of a global with the given name. | ||
Limitations: Due to peculiarities with the behavior of `globalThis`, "globally defined" only includes `var` declarations in `declare global` blocks, not `let` or `const` declarations. | ||
@example | ||
``` | ||
import type {FindGlobalType} from 'type-fest'; | ||
declare global { | ||
const foo: number; // let and const don't work | ||
var bar: string; // var works | ||
} | ||
type FooType = FindGlobalType<'foo'> //=> never (let/const don't work) | ||
type BarType = FindGlobalType<'bar'> //=> string | ||
type OtherType = FindGlobalType<'other'> //=> never (no global named 'other') | ||
``` | ||
@category Utilities | ||
*/ | ||
export type FindGlobalType<Name extends string> = typeof globalThis extends Record<Name, infer T> ? T : never; | ||
|
||
/** | ||
Tries to find one or more types from their globally-defined constructors. | ||
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 this case. Declaring a class in a `declare global` block won't work, instead you must declare its type using an interface and declare its constructor as a `var` (*not* `let`/`const`) inside the `declare global` block. | ||
@example | ||
``` | ||
import type {FindGlobalInstanceType} from 'type-fest'; | ||
class Point { | ||
constructor(public x: number, public y: number) {} | ||
} | ||
type PointLike = Point | FindGlobalInstanceType<'DOMPoint'>; | ||
``` | ||
@example | ||
``` | ||
import type {FindGlobalInstanceType} from 'type-fest'; | ||
declare global { | ||
// Class syntax won't add the key to `globalThis` | ||
class Foo {} | ||
// interface + constructor style works | ||
interface Bar {} | ||
var Bar: new () => Bar; // Not let or const | ||
} | ||
type FindFoo = FindGlobalInstanceType<'Foo'>; // Doesn't work | ||
type FindBar = FindGlobalInstanceType<'Bar'>; // Works | ||
``` | ||
@category Utilities | ||
*/ | ||
export type FindGlobalInstanceType<Name extends string> = | ||
Name extends string | ||
? typeof globalThis extends Record<Name, abstract new (...arguments: any[]) => infer T> ? T : never | ||
: never; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* eslint-disable no-var, unicorn/prevent-abbreviations */ | ||
import {expectAssignable, expectNotAssignable, expectType} from 'tsd'; | ||
import type {FindGlobalInstanceType, FindGlobalType} from '..'; | ||
|
||
declare class NonGlobalES6Class {} | ||
declare var nonGlobalVar: number; | ||
declare let nonGlobalLet: number; | ||
declare const nonGlobalConst: number; | ||
|
||
declare global { | ||
class GlobalES6Class {} | ||
var globalVar: string; | ||
let globalLet: number; | ||
const globalConst: number; | ||
|
||
type GlobalClass = {foo: string}; | ||
var GlobalConstructorVarStyle: new () => GlobalClass; | ||
let GlobalConstructorLetStyle: new () => GlobalClass; | ||
const GlobalConstructorConstStyle: new () => GlobalClass; | ||
|
||
type GlobalTypeAlias = {value: string}; | ||
|
||
var nonConstructorFunction: () => Date; | ||
} | ||
|
||
// === FindGlobalType === | ||
|
||
// Success | ||
declare const foundGlobalVar: FindGlobalType<'globalVar'>; | ||
expectType<string>(foundGlobalVar); | ||
|
||
// Failures | ||
declare const foundNonGlobalES6Class: FindGlobalType<'nonGlobalVar'>; | ||
expectType<never>(foundNonGlobalVar); | ||
declare const foundNonGlobalVar: FindGlobalType<'nonGlobalVar'>; | ||
expectType<never>(foundNonGlobalVar); | ||
declare const foundNonGlobalLet: FindGlobalType<'nonGlobalLet'>; | ||
expectType<never>(foundNonGlobalLet); | ||
declare const foundNonGlobalConst: FindGlobalType<'nonGlobalConst'>; | ||
expectType<never>(foundNonGlobalConst); | ||
|
||
declare const foundGlobalLet: FindGlobalType<'globalLet'>; | ||
expectType<never>(foundGlobalLet); | ||
declare const foundGlobalConst: FindGlobalType<'globalConst'>; | ||
expectType<never>(foundGlobalConst); | ||
|
||
// === FindGlobalInstanceType === | ||
|
||
// Success | ||
declare const foundInstanceDate: FindGlobalInstanceType<'Date'>; | ||
expectType<Date>(foundInstanceDate); | ||
declare const foundInstanceMultiple: FindGlobalInstanceType<'Date' | 'Error'>; | ||
expectType<Date | Error>(foundInstanceMultiple); | ||
declare const foundInstanceMultiplePartial: FindGlobalInstanceType<'Date' | 'Error' | 'NonExistentType'>; | ||
expectType<Date | Error>(foundInstanceMultiplePartial); | ||
declare const foundInstanceGlobalConstructorVarStyle: FindGlobalInstanceType<'GlobalConstructorVarStyle'>; | ||
expectType<GlobalClass>(foundInstanceGlobalConstructorVarStyle); | ||
|
||
// Failures | ||
declare const foundInstanceNonExistentType: FindGlobalInstanceType<'NonExistentType'>; | ||
expectType<never>(foundInstanceNonExistentType); | ||
declare const foundInstanceNonGlobalES6Class: FindGlobalInstanceType<'NonGlobalES6Class'>; | ||
expectType<never>(foundInstanceNonGlobalES6Class); | ||
|
||
declare const foundInstanceGlobalTypeAlias: FindGlobalInstanceType<'GlobalTypeAlias'>; | ||
expectType<never>(foundInstanceGlobalTypeAlias); | ||
declare const foundInstanceGlobalES6Class: FindGlobalInstanceType<'GlobalES6Class'>; | ||
expectType<never>(foundInstanceGlobalES6Class); | ||
declare const foundInstanceGlobalConstructorLetStyle: FindGlobalInstanceType<'GlobalConstructorLetStyle'>; | ||
expectType<never>(foundInstanceGlobalConstructorLetStyle); | ||
declare const foundInstanceGlobalConstructorConstStyle: FindGlobalInstanceType<'GlobalConstructorConstStyle'>; | ||
expectType<never>(foundInstanceGlobalConstructorConstStyle); | ||
declare const foundInstanceGlobalNonConstructorFunction: FindGlobalInstanceType<'nonConstructorFunction'>; | ||
expectType<never>(foundInstanceGlobalNonConstructorFunction); |