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

I tried to make all these types globally available in my project, but I failed. #470

Closed
Evertt opened this issue Sep 22, 2022 · 5 comments
Closed

Comments

@Evertt
Copy link

Evertt commented Sep 22, 2022

In my src folder I have a global.d.ts file, which already starts with the line /// <reference types="vue/macros-global" /> and that works fine. So I thought I could just add another line /// <reference types="type-fest" />. But unfortunately that does not do the trick.

Is it because your index.d.ts uses export statements? If so, would you be willing to make another file that exports the types in a way that I can "import" them in my global.d.ts?

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • The funding will be given to active contributors.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@sindresorhus
Copy link
Owner

Global types are generally discouraged and I don't intend to change anything to support them here.

However, you could maybe do this yourself by importing the types using import in the global types file and manually declare global type aliases to the utilities you need.

@sindresorhus sindresorhus closed this as not planned Won't fix, can't repro, duplicate, stale Sep 29, 2022
@Evertt
Copy link
Author

Evertt commented Sep 30, 2022

Can I just ask, why are global types discouraged?

@sindresorhus
Copy link
Owner

Global types are bad in packages as they can affect types elsewhere in your dependency tree. Exposing types yourself in your own global type definition in a non-package project is totally fine though.

@Evertt
Copy link
Author

Evertt commented Sep 30, 2022

I'm sorry, but either what you said is incorrect or I don't quite understand what you just said.

If you let TS generate a global.d.ts file in your package that declares all your types without any imports or exports, then all the types in that file will be globally available, but at first, only in your package. Those types won't be globally available in my project unless I write something along the lines of /// <reference types="type-fest/global" /> in my own global.d.ts. In other words, there is no risk of accidentally affecting types elsewhere in my dependency tree, because I know I am choosing to make all your types global. And if I do need a type from another dependency that has the same name as one of your types, then I can just explicitly import that type in the one file I need it.

And you say:

However, you could maybe do this yourself by importing the types using import in the global types file and manually declare global type aliases to the utilities you need.

Which indeed I'm already doing for a few types, like so:

// This is in my own global.d.ts file

declare type Class<T, Arguments extends unknown[] = any[]> =
  import("type-fest").Class<T, Arguments>

And that works, but I'm simply asking, could you make it easier for me to do exactly the same thing, but then for all your types, so that I don't have repeat that line of code for every single type your library contains.

For example, Vue 3 has an experimental feature that they call Reactivity Transform. Which, when turned on, offers globally accessible functions, like $ref() that can do some nifty stuff. And the only thing I need to do to make all those global functions known to TS, is by adding /// <reference types="vue/macros-global" /> at the top of my global.d.ts.

It's just so convenient, I don't see why you wouldn't give developers the option? If a developer thinks it's bad practice then they can simply choose to not add /// <reference types="type-fest/global" /> to their global.d.ts and so they won't be inconvenienced by its existence.

I mean, TS itself has a bunch of globally available utility types. And aren't we all glad that we don't have to write import type { Partial } from "typescript" every time we want to use the Partial type for example?

I apologize if the tone of my comment sounds antagonizing. It's just that I really don't understand your reasoning about why it's bad practice, and I don't see how adding this feature could negatively affect people who don't want to use the feature, and I would soooooo love to be able to just get this convenience.

@qzsiniong
Copy link

qzsiniong commented Dec 5, 2023

// types/type-fest.d.ts
import { IsEqual } from 'type-fest';

declare global {
  export namespace TypeFest {
    export type * from 'type-fest';
    import('type-fest');
  }

  export namespace T {
    export type * from 'type-fest';
    import('type-fest');

    export type ConditionalExactKeys<Base, Condition> = NonNullable<
      // Wrap in `NonNullable` to strip away the `undefined` type from the produced union.
      {
        // Map through all the keys of the given base type.
        // [Key in keyof Base]: [Condition] extends [Base[Key]] // Pick only keys with types extending the given `Condition` type.
        [Key in keyof Base]: IsEqual<Base[Key], Condition> extends true // Pick only keys with types exact equal the given `Condition` type.
          ? // Retain this key since the condition passes.
            Key
          : // Discard this key since the condition fails.
            never;

        // Convert the produced object into a union type of the keys which passed the conditional test.
      }[keyof Base]
    >;
  }
}

export {};
// tsconfig.json
{
  "include": [
    "types/type-fest.d.ts",
  ]
}

useage

// type T1 = "a" | "b" | "b.c"
type T1 = T.Paths<{ a: string; b: { c: number } }>;

// type T2 = "fooBar"
type T2 = TypeFest.CamelCase<'foo-bar'>;

type Foo = {
  a: number;
  b?: number;
  c: 1 | 2 | 3;
};
// type T3 = "c" | "a" | "b"
type T3 = T.ConditionalKeys<Foo, number | undefined>;

// type T4 = "b"
type T4 = T.ConditionalExactKeys<Foo, number | undefined>;

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

No branches or pull requests

3 participants