YLfjuk / core

🌱 The core packages for @YLfjuk projects
MIT License
1 stars 0 forks source link

Extract Functions as types #3

Open YLfjuk opened 6 days ago

YLfjuk commented 6 days ago

Is your feature request related to a specific package? Please specify. @ylfjuk-core/types

Is your feature request related to a problem? Please describe. Provide more options regarding the handling of functions

Describe the solution you'd like Allow to extract the FN type itself if the extractFNReturnType isn't specified

Describe alternatives you've considered change the second parameter into a union type of extract options (false | 'extractFN' | 'extractFNReturnType')

Additional context

type ExtractOption = false | 'extractFN' | 'extractFNReturnType';

export type ExtractValues<
    T,
    extractOption extends NoUnion<ExtractOption> = false
> = T extends FN<infer R>
    ? extractOption extends 'extractFNReturnType'
        ? ExtractValues<R, extractOption>
        : extractOption extends 'extractFN'
        ? T
        : never
    : T extends object
    ? T extends Date
        ? T
        : ExtractValues<ValueOf<T>, extractOption>
    : T;

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html

YLfjuk commented 6 days ago

import type { FN, IsDisjointUnion, ValueOf } from './utils';

type ExtractionOptions = false | 'extractFn' | 'extractFnReturnType';

export type ExtractValues<
    T,
    extractOption extends ExtractionOptions = false
> = IsDisjointUnion<extractOption> extends true
    ? `error: extractOption was provided too many values. It must be one of the ExtractionOptions`
    : T extends FN<infer R>
    ? extractOption extends 'extractFnReturnType'
        ? ExtractValues<R, extractOption>
        : extractOption extends 'extractFn'
        ? T
        : never
    : T extends object
    ? T extends Date
        ? T
        : ExtractValues<ValueOf<T>, extractOption>
    : T;

//?---------------------

const obj = {
    Bob: 'bob',
    Bert: {
        name: 'bert',
    },
    Other: {
        index: 'other',
        tmp: () => 0 as const,
        user(username: string) {
            return `other/${username}` as const;
        },
    },
} as const;

type Actual = ExtractValues<typeof obj, 'extractFn' | false>;
//   ^? type Actual = "error: extractOption was provided too many values. It must be one of the ExtractionOptions"