【问题标题】:Autocomplete in return type Typescript based on input object基于输入对象的返回类型 Typescript 中的自动完成
【发布时间】:2020-07-07 04:37:40
【问题描述】:

更新:感谢https://stackoverflow.com/users/5575595/drag13,完整版可以在这里找到:https://github.com/web-ridge/react-ridge-translations/blob/main/src/index.ts

我正在为 React / React Native 开发翻译库,但我无法让这些类型正常工作。

https://github.com/web-ridge/react-ridge-translations

您可以通过以下方式创建翻译

// first describe which languages are allowed/required (Typescript)
type TranslationLanguages = {
    nl: string
    fr: string
    en: string
}

// create a translation object with your translations
export default const translate = createTranslations<TranslationLanguages>({
  homeScreen:{
    yesText: {
      nl: 'Ja',
      fr: 'Oui',
      be: 'Yes',
    },
    welcomeText: ({ firstName }: { firstName: string }) => ({
      nl: `Hoi ${firstName}`,
      fr: `Hello ${firstName}`,
      be: `Hello ${firstName}`,
    }),
  }
}, {
    language: 'nl',
    fallback: 'en',
})

库将对象更改为以下

{
  homeScreen:{
    yesText: 'Ja',
    welcomeText: ({ firstName }: { firstName: string }) => `Hoi ${firstName}`,
  }
}

在您的组件中,您将以这种方式使用类型

  const {yesText,welcomeText} = translate.use().appScreen

它不会自动完成类型。

库代码(简体)

type val<T> = (...params: any[]) => T
type val1<T> = T

type Translations<T> = {
    [group: string]: {
        [key: string]:  val<T> | val1<T>
    },
}
type TranslationsObject<T> = {
    translations: Translations<string>,
    use: () => Translations<string>;
}
export function createTranslations<T>(t: Translations<T>): TranslationsObject<T> 

如何让 Typescript 明白它需要自动完成?

【问题讨论】:

  • 你的第一个链接返回 404 :(
  • 已修复 master 分支已更改为 main

标签: reactjs typescript


【解决方案1】:

因此,您希望允许 TypeScript 自己定义接口。在这种情况下,您需要使用更多的泛型。像这样的:

type ValueOf<T> = T[keyof T]; 
type Translations<TGroup> = {
   [group in keyof TGroup]: { [key in keyof ValueOf<TGroup>]: ValueOf<TGroup>[key] }
}

type TranslationsObject<TGroup> = {
    translations: Translations<TGroup>,
    use: () => Translations<TGroup>;
}

export function createTranslations<TGroup>(data: TGroup): TranslationsObject<TGroup> { }


const test = createTranslations({
  homeScreen:{
    yesText: {
      nl: 'Ja',
      fr: 'Oui',
      be: 'Yes',
    },
    welcomeText: ({ firstName }: { firstName: string }) => ({
      nl: `Hoi ${firstName}`,
      fr: `Hello ${firstName}`,
      be: `Hello ${firstName}`,
    }),
  }
});

const x  = test.use().homeScreen.yesText

类型检查现在应该可以正常工作。这个好看吗?

使用评论中的代码更新

【讨论】:

  • 我想我会成功的!非常感谢,我添加了一个使其完全正常工作的内容,也许可以编辑答案 ``` type ValueOf = T[keyof T]; type Translations = { [keyof TGroup 中的组]: { [keyof ValueOf 中的键]: val | val1 } } ```
  • @RichardLindhout 看起来很棒!我已经更新了答案。
  • 工作几乎完美,但它还不理解welcomeText:({ firstName }:它说:并非所有类型'string | val'的成分都是可调用的。类型'string'没有呼叫签名。我怀疑是否有可能基于此工作:stackoverflow.com/questions/14953359/…
  • 我刚刚发布了该软件包的第 1 版。感谢您的帮助!
  • 很高兴为您提供帮助:)
【解决方案2】:

问题在这里

type Translations<T> = {
    [group: string]: {
        [key: string]:  val<T> | val1<T>
    },
}

由于索引器声明,TypeScript 对内部结构一无所知。如果你想拥有更多强类型,这里是选项:

type val<T> = (...params: any[]) => T
type val1<T> = T
type TransltionGroup = 'homeScreen' | 'personalCabinet';
type Translations<T> = {
    [group in TransltionGroup]: {
        [key: string]:  val<T> | val1<T>
    }
}
type TranslationsObject<T> = {
    translations: Translations<string>,
    use: () => Translations<string>;
}
export function createTranslations<T>(t: Translations<T>): TranslationsObject<T> { }

const test = createTranslations({ homeScreen: { test: '4' }, personalCabinet: { test: '6' } });

const x  = test.use().personalCabinet

当然,您可以声明子组的类型

希望这会有所帮助!

【讨论】:

  • 这看起来不错!但我希望自动组,因为我不想让我的打字稿用户自己定义它
  • 在这种情况下(如果我理解正确的话)看起来你需要一个更通用的。如果你不介意我会再回答一个,因为问题有点不同
  • 没问题,非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 2020-09-04
  • 2019-06-07
  • 2020-05-02
  • 2019-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多