简体   繁体   English

使用字符串定义类型与 object 文字属性

[英]Define Type with strings versus object literal properties

I've poured over the TS docs, but can't seem to find an answer as to why the following is illegal.我已经倾注了 TS 文档,但似乎无法找到为什么以下内容是非法的答案。

I'm able to define a union type with strings, yet if I create the same union type with references to object properties, which ultimately references the same string values, the compiler isn't happy.我可以用字符串定义联合类型,但是如果我使用 object 属性的引用创建相同的联合类型,最终引用相同的字符串值,编译器就会不高兴。

Demo via typescript playground 通过 typescript 操场进行演示

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

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

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

The errors are as follows.错误如下。 Why is this a namespace issue?为什么这是一个命名空间问题?

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

Ultimately, it'd be nice to have a Column interface the defines the supported sort order types, while then instancing a Column with SortOrderStatic to avoid magic strings, but per the above, this doesn't seem possible.最终,最好有一个Column接口来定义支持的排序顺序类型,然后用SortOrderStatic实例化一个Column以避免魔术字符串,但根据上述情况,这似乎是不可能的。

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

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

If I define the interface as follows (with SortOrderWithStrings ), and then attempt to use SortOrderStatic , the compiler once again isn't happy.如果我按如下方式定义接口(使用SortOrderWithStrings ),然后尝试使用SortOrderStatic ,编译器再次不高兴。

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

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

Fails with:失败:

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

It's clear I'm missing something fundamental here, and I appreciate any insight.很明显,我在这里遗漏了一些基本的东西,我很感激任何见解。

It's clear I'm missing something fundamental here很明显我在这里遗漏了一些基本的东西

Yes, you are confusing compile-time with runtime: unless the compile-time type is a literal string, the compiler cannot guarantee that the runtime access of an object property is the string you think it is.是的,您将编译时与运行时混淆了:除非编译时类型是文字字符串,否则编译器无法保证 object 属性的运行时访问是您认为的字符串。 Your object property is type string , which means at runtime it could be any string.您的 object 属性是string类型,这意味着在运行时它可以是任何字符串。

The string literal is immutable (and so statically verifiable), the object property access not so much.字符串文字是不可变的(因此可以静态验证),object 属性访问量不大。

In your particular case I would just use an enum :在您的特定情况下,我将只使用enum

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

export { SortOrder }

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

This will maintain type-safety, you can't pass any ol' string to something that expects a SortOrder : ( Playground )这将保持类型安全,您不能将任何 ol' 字符串传递给需要SortOrder的东西:( Playground

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM