question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Types] Consider exposing PropertyNames types

See original GitHub issue

🚀 Feature Proposal

Please consider exposing NonFunctionPropertyNames<T>, FunctionPropertyNames<T> and ConstructorPropertyNames<T>

Motivation

Sometimes types are not infered as desired. Exposing these types could help developers to provide Typescript hints to infer types in some corner cases

Example

Consider your actual type spyOn:

    function spyOn<T extends {}, M extends NonFunctionPropertyNames<Required<T>>>(
        object: T,
        method: M,
        accessType: 'get'
    ): SpyInstance<Required<T>[M], []>;
    function spyOn<T extends {}, M extends NonFunctionPropertyNames<Required<T>>>(
        object: T,
        method: M,
        accessType: 'set'
    ): SpyInstance<void, [Required<T>[M]]>;
    function spyOn<T extends {}, M extends FunctionPropertyNames<Required<T>>>(
        object: T,
        method: M
    ): Required<T>[M] extends (...args: any[]) => any
        ? SpyInstance<ReturnType<Required<T>[M]>, ArgsType<Required<T>[M]>>
        : never;
    function spyOn<T extends {}, M extends ConstructorPropertyNames<Required<T>>>(
        object: T,
        method: M
    ): Required<T>[M] extends new (...args: any[]) => any
        ? SpyInstance<InstanceType<Required<T>[M]>, ConstructorArgsType<Required<T>[M]>>
        : never;

Consider a mock on global.Date:

   const dateSpy: jest.SpyInstance<Date> = jest.spyOn<
          NodeJS.Global,
          'Date'
    >(global, 'Date');

The actual code throws the following syntax error:

Type 'SpyInstance<string, []>' is not assignable to type 'SpyInstance<Date, any>'.
  Types of property 'mock' are incompatible.
    Type 'MockContext<string, []>' is not assignable to type 'MockContext<Date, any>'.
      Type 'string' is not assignable to type 'Date'.t

Why is this happening?

Well, if we look NodeJS.Global Types:

interface Global {
        Array: typeof Array;
        ArrayBuffer: typeof ArrayBuffer;
        Boolean: typeof Boolean;
        Buffer: typeof Buffer;
        DataView: typeof DataView;
        Date: typeof Date;
...
}

Then, if we look for Date

interface DateConstructor {
    new(): Date;
    new(value: number | string): Date;
    new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
    (): string;
    readonly prototype: Date;
    ...
}

declare var Date: DateConstructor;

As you can realize, Typescript tries to match spyOn in the order provided in the type file. As long as DateConstructor is a valid FunctionPropertyNames<T>, Typescript asumes I’m using the following call:

    function spyOn<T extends {}, M extends FunctionPropertyNames<Required<T>>>(
        object: T,
        method: M
    ): Required<T>[M] extends (...args: any[]) => any
        ? SpyInstance<ReturnType<Required<T>[M]>, ArgsType<Required<T>[M]>>
        : never;

But as long as Date includes (): string, Typescript infers its a SpyInstance<string, []>

Solution

Exposing these types (NonFunctionPropertyNames<T>, FunctionPropertyNames<T> and ConstructorPropertyNames<T>) would help us provide hints to Typescript:

    const dateSpy: jest.SpyInstance<Date> = jest.spyOn<
          NodeJS.Global,
          ConstructorPropertyNames<NodeJS.Global>
        >(global, 'Date');

Do you think it could be possible? Thank you so much for your time and effort

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:6
  • Comments:8 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
mrazauskascommented, Feb 21, 2022

Interestingly since #12089 jest-mock is already exporting MethodKeysOf, PropertyKeysOf, ConstructorArgumentsOf types which are equivalent to FunctionPropertyNames, NonFunctionPropertyNames, ConstructorPropertyNames (edit: apparently ConstructorPropertyNames wasn’t present in jest-mock types, the issue is referencing @types/jest):

https://github.com/facebook/jest/blob/7d4595eb935556b8214e1dda45b0b68dfc67068f/packages/jest-mock/src/index.ts#L36-L41

1reaction
SimenBcommented, Feb 10, 2022

PR welcome 🙂

Read more comments on GitHub >

github_iconTop Results From Across the Web

Advanced TypeScript 4.8 Concepts: Classes and Types
Gain a deeper understanding of how TypeScript's type system enhances classes via interfaces, access modifiers, decorators and other features ...
Read more >
'<propertyname>' cannot be exposed to COM as a property 'Let'
A class using a COMClassAttribute attribute block declares a Public property with data type Object . A Visual Basic 6.0 program can access ......
Read more >
typescript-cheatsheet - GitHub Pages
The cheatsheet contains references to types, classes, decorators, ... Optional Properties; Index Signatures (Dynamic Property Names); Implements Keyword.
Read more >
Exposing database field to 2 properties - Stack Overflow
This Search method will take as parameters the type of search you want to do (being Equal to, Contains, Greater than, etc.) and...
Read more >
quicktype under the hood
Types. Before exploring these stages in detail, let's discuss the ... the Simplify stage) that the property names are probably not fixed, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found