【问题标题】:How do I call an array of function names in Typescript?如何在 Typescript 中调用函数名数组?
【发布时间】:2021-05-30 16:55:01
【问题描述】:

我想在给定数组函数名称的情况下动态运行函数,但 TS 对 duration[unit] 提出了投诉,并显示以下消息:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Duration'.

No index signature with a parameter of type 'string' was found on type 'Duration'.ts(7053)
const duration: Duration = moment.duration(5000)
const unitsOfTime = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds']
const timeBreakdown = unitsOfTime.map((unit) => duration[unit]())

【问题讨论】:

标签: typescript momentjs


【解决方案1】:

您必须将as const 添加到unitsOfTime,因为TS 将其推断为stirng[]duration 不是索引对象。

看看Duration接口:

  interface Duration {
    clone(): Duration;

    humanize(argWithSuffix?: boolean, argThresholds?: argThresholdOpts): string;
    
    humanize(argThresholds?: argThresholdOpts): string;

    abs(): Duration;

    as(units: unitOfTime.Base): number;
    get(units: unitOfTime.Base): number;

    milliseconds(): number;
    asMilliseconds(): number;

    seconds(): number;
    asSeconds(): number;

    minutes(): number;
    asMinutes(): number;

    hours(): number;
    asHours(): number;

    days(): number;
    asDays(): number;

    weeks(): number;
    asWeeks(): number;

    months(): number;
    asMonths(): number;

    years(): number;
    asYears(): number;

    add(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
    subtract(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;

    locale(): string;
    locale(locale: LocaleSpecifier): Duration;
    localeData(): Locale;

    toISOString(): string;
    toJSON(): string;

    isValid(): boolean;

    /**
     * @deprecated since version 2.8.0
     */
    lang(locale: LocaleSpecifier): Moment;
    /**
     * @deprecated since version 2.8.0
     */
    lang(): Locale;
    /**
     * @deprecated
     */
    toIsoString(): string;
  }

您只能使用现有的道具作为索引。

当您添加as const 时,TS 将允许您使用unitsOfTime 值作为Durarion 索引

import * as moment from 'moment'

const duration = moment.duration(5000)
const unitsOfTime = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds'] as const
const timeBreakdown = unitsOfTime.map((unit) => duration[unit]())

`

【讨论】:

    【解决方案2】:

    在咨询了一些朋友和更多想法后,我意识到通过字符串数组进行映射根本不是一个好主意,因为这些是魔术字符串,这意味着下一个看这个的人对什么方法有很好的理解Duration 对象响应。

    更好的方法是通过显式配置映射

    // First we define what should unit of time look like
    interface unitOfTimeMap {
      unit: string,
      shortUnit: string,
      amount: (duration: Duration) => number
    }
    
    // Then we have an explicit configuration of what unit of time we and how they should be mapped to the duration object.
    
    const unitsOfTimeMapping: unitOfTimeMap[] = [
      {
        unit: 'years',
        amount: (duration: Duration): number => duration.years()
      },
      {
        unit: 'months',
        amount: (duration: Duration): number => duration.months()
      },
      {
        unit: 'weeks',
        amount: (duration: Duration): number => duration.weeks()
      },
      {
        unit: 'days',
        amount: (duration: Duration): number => duration.days()
      },
      {
        unit: 'hours',
        amount: (duration: Duration): number => duration.hours()
      },
      {
        unit: 'minutes',
        amount: (duration: Duration): number => duration.minutes()
      },
      {
        unit: 'seconds',
        amount: (duration: Duration): number => duration.seconds()
      },
    ]
    
    // Now TS knows exactly what we're working with and no longer complains
    const duration: Duration = moment.duration(5000);
    const timeBreakdown = unitsOfTimeMapping.map((unitOfTime) => unitOfTime.amount(duration))
    

    【讨论】:

      【解决方案3】:

      您可以暂时尝试以下解决方案。 使用 get 方法获取时刻持续时间和 unit as unitOfTime.Base

      import moment, { Duration , unitOfTime } from "moment-timezone";
      
      
      const duration: Duration = moment.duration(5000);
      const unitsOfTime: unitOfTime.Base[] = [
        "years",
        "months",
        "weeks",
        "days",
        "hours",
        "minutes",
        "seconds",
      ];
      const timeBreakdown = unitsOfTime.map((unit:unitOfTime.Base) =>  duration.get(unit));
      
      console.log(timeBreakdown);
      

      【讨论】:

        猜你喜欢
        • 2012-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-06
        相关资源
        最近更新 更多