【问题标题】:How do I define Type with strings versus object literal properties?如何使用字符串与对象文字属性定义类型?
【发布时间】:2021-03-27 15:22:01
【问题描述】:

我翻阅了 TS 文档,但似乎无法找到关于以下内容为何非法的答案。

我可以用字符串定义一个联合类型,但是如果我使用对象属性的引用创建相同的联合类型,最终引用相同的字符串值,编译器就会不高兴。

Demo via typescript playground

// Success
export type SortOrderWithStrings = 'asc' | 'desc';

export const SortOrderStatic = {
  ASC: 'asc',
  DESC: 'desc',
}

// Fail
export type SortOrderWithObject = SortOrderStatic.ASC | SortOrderStatic.DESC;

错误如下。为什么这是命名空间问题?

Cannot find namespace 'SortOrderStatic'
Exported type alias 'SortOrderReference' has or is using private name 'SortOrderType'

最终,最好有一个Column 接口来定义支持的排序顺序类型,然后用SortOrderStatic 实例化一个Column 以避免魔术字符串,但根据上述情况,这并不似乎有可能。

interface Column {
  label: string;
  defaultSortOrder: SortOrderWithObject;
}

const MyColumn: Column = {
  label: 'My Column',
  defaultSortOrder: SortOrderStatic.ASC
}

如果我如下定义接口(使用SortOrderWithStrings),然后尝试使用SortOrderStatic,编译器再次不高兴。

interface Column {
  label: string;
  defaultSortOrder: SortOrderWithStrings;
}

const MyColumn: Column = {
  label: 'My Column',
  defaultSortOrder: SortOrderStatic.ASC
}

失败:

Type 'string' is not assignable to type 'SortOrderWithStrings'.

很明显我在这里遗漏了一些基本的东西,我很感激任何见解。

【问题讨论】:

  • “很明显我在这里遗漏了一些基本的东西”是的,你把 compile-timeruntime 混淆了。除非 编译时类型 是文字字符串,否则编译器无法保证对象属性的运行时访问是您认为的字符串。您的对象属性类型为string,这意味着在运行时它可以是any 字符串。字符串字面量是不可变的(因此可以静态验证),对象属性访问量不大。
  • @JaredSmith 谢谢,好的,有道理。我想知道如果SortOrderStatic 的类型为interface { [x: string]: string; },编译器是否可以推断出预期的运行时类型。这还不够明确吗?
  • 在这种情况下我会使用an enum
  • @JaredSmith 谢谢,我认为您更新的评论对我有用。编译器无法知道我最终的ASC 会是什么。
  • 没错。几乎每个人(包括我刚开始时的我!)对 TS 的所有问题都来自这种混淆。

标签: javascript typescript


【解决方案1】:

很明显我在这里遗漏了一些基本的东西

是的,您将编译时与运行时混淆了:除非编译时类型是文字字符串,否则编译器无法保证对象属性的运行时访问是您认为的字符串是。您的对象属性类型为string,这意味着在运行时它可以是任何字符串。

字符串字面量是不可变的(因此可以静态验证),对象属性的访问量不大。

在您的特定情况下,我只会使用 an enum:

enum SortOrder {
  ASC = 'ASC',
  DESC = 'DESC',
}

export { SortOrder }

import { SortOrder } from 'something';
SortOrder.ASC; // ASC as a string

这将保持类型安全,您不能将任何 ol' 字符串传递给需要 SortOrder: (Playground) 的东西

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 2022-01-03
    • 2021-08-10
    • 2020-01-07
    • 2020-12-08
    相关资源
    最近更新 更多