有没有办法让 TypeScript 从函数参数值中推断返回类型?

huangapple go评论71阅读模式
英文:

is there any way to let Typescript infer the return type from the function argument value?

问题

type ValueType = 'integer' | 'string' | 'number' | 'date' | 'dateTime' | 'boolean' | '';

function toValueType<S>(v: S, valueType: 'integer'): number;
function toValueType<S>(v: S, valueType: 'number'): number;
function toValueType<S>(v: S, valueType: 'date'): Date | undefined;
function toValueType<S>(v: S, valueType: 'dateTime'): Date | undefined;
function toValueType<S>(v: S, valueType: 'string'): string;
function toValueType<S>(v: S, valueType: ''): S;
function toValueType<S>(v: S, valueType: ValueType): any {
    switch (valueType) {
        case 'integer':
            return To.int(v); // return number
        case 'number':
            return To.number(v); // return number
        case 'date':
            return To.date(v); // return Date|undefined
        case 'dateTime':
            return To.dateTime(v); // return Date|undefined
        case 'string':
            return To.string(v); // return string
        case 'boolean':
            return To.boolean(v); // return boolean
        default:
            return v; // return source
    }
}
英文:

is there any way to let Typescript infer the return type from the valueType argument instead of overloads?

 type ValueType = &#39;integer&#39; | &#39;string&#39; | &#39;number&#39; | &#39;date&#39; | &#39;dateTime&#39; | &#39;boolean&#39; | &#39;&#39;;

   function toValueType&lt;S&gt;(v: S, valueType: &#39;integer&#39;): number;
   function toValueType&lt;S&gt;(v: S, valueType: &#39;number&#39;): number;
   function toValueType&lt;S&gt;(v: S, valueType: &#39;date&#39;): Date | undefined;
   function toValueType&lt;S&gt;(v: S, valueType: &#39;dateTime&#39;): Date | undefined;
   function toValueType&lt;S&gt;(v: S, valueType: &#39;string&#39;): string;
   function toValueType&lt;S&gt;(v: S, valueType: &#39;&#39;): S;
   function toValueType&lt;S&gt;(v: S, valueType: ValueType): any {
        switch (valueType) {
            case &#39;integer&#39;:
                return To.int(v); // return number
            case &#39;number&#39;:
                return To.number(v); // return number
            case &#39;date&#39;:
                return To.date(v); // return Date|undefined
            case &#39;dateTime&#39;:
                return To.dateTime(v); // return Date|undefined
            case &#39;string&#39;:
                return To.string(v); // return string
            case &#39;boolean&#39;:
                return To.boolean(v); // return boolean
            default:
                return v; // return source
        }
    } 

答案1

得分: 0

You can create a type alias which represents a mapping of each string literal in your ValueType union to its corresponding expected return type, and create another generic type parameter to use for selecting the appropriate type in a conditional return type:

TS Playground

type ValueMap = {
  boolean: boolean;
  date: Date | undefined;
  dateTime: Date | undefined;
  integer: number;
  number: number;
  string: string;
};

type ValueType = keyof ValueMap | &quot;&quot;;

declare function toValueType&lt;T, K extends ValueType&gt;(
  v: T,
  valueType: K,
): K extends keyof ValueMap ? ValueMap[K] : T;

declare const v: { _type: &quot;example&quot; };

const r0 = toValueType(v, &quot;boolean&quot;);
    //^? const r0: boolean

const r1 = toValueType(v, &quot;date&quot;);
    //^? const r1: Date | undefined

const r2 = toValueType(v, &quot;dateTime&quot;);
    //^? const r2: Date | undefined

const r3 = toValueType(v, &quot;integer&quot;);
    //^? const r3: number

const r4 = toValueType(v, &quot;number&quot;);
    //^? const r4: number

const r5 = toValueType(v, &quot;string&quot;);
    //^? const r5: string

const r6 = toValueType(v, &quot;&quot;);
    //^? const r6: { _type: &quot;example&quot;; }

toValueType(v, &quot;something else&quot;); /* Error
               ~~~~~~~~~~~~~~~~
Argument of type &#39;&quot;something else&quot;&#39; is not assignable to parameter of type &#39;ValueType&#39;.(2345) */
英文:

You can create a type alias which represents a mapping of each string literal in your ValueType union to its corresponding expected return type, and create another generic type parameter to use for selecting the appropriate type in a conditional return type:

TS Playground

type ValueMap = {
  boolean: boolean;
  date: Date | undefined;
  dateTime: Date | undefined;
  integer: number;
  number: number;
  string: string;
};

type ValueType = keyof ValueMap | &quot;&quot;;

declare function toValueType&lt;T, K extends ValueType&gt;(
  v: T,
  valueType: K,
): K extends keyof ValueMap ? ValueMap[K] : T;

declare const v: { _type: &quot;example&quot; };

const r0 = toValueType(v, &quot;boolean&quot;);
    //^? const r0: boolean

const r1 = toValueType(v, &quot;date&quot;);
    //^? const r1: Date | undefined

const r2 = toValueType(v, &quot;dateTime&quot;);
    //^? const r2: Date | undefined

const r3 = toValueType(v, &quot;integer&quot;);
    //^? const r3: number

const r4 = toValueType(v, &quot;number&quot;);
    //^? const r4: number

const r5 = toValueType(v, &quot;string&quot;);
    //^? const r5: string

const r6 = toValueType(v, &quot;&quot;);
    //^? const r6: { _type: &quot;example&quot;; }

toValueType(v, &quot;something else&quot;); /* Error
               ~~~~~~~~~~~~~~~~
Argument of type &#39;&quot;something else&quot;&#39; is not assignable to parameter of type &#39;ValueType&#39;.(2345) */

huangapple
  • 本文由 发表于 2023年5月25日 12:20:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76328916.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定