访问在打字稿接口定义中定义的值

Accessing a value defined in a typescript interface defintion

我是打字稿的新手,有一个问题我似乎无法以 Google 可用的方式提出。

假设我定义了这个接口:

interface MyInterface {
  myField: "myValue"
}

我希望能够写出这行代码:

const value = MyInterface.myField; // expect value to equal "myValue"

这无法编译,但我想知道是否有某种方法可以实现此行为。由于 myField 的值是在打字稿编译时定义的,我相信这应该是可能的。但是我不知道该怎么做。

任何建议表示赞赏。谢谢!

更新:

我想我需要提供更多信息。我正在尝试通过阅读这篇文章来减少样板文件并在 redux 应用程序中维护类型安全:

https://medium.com/@resir014/a-type-safe-approach-to-redux-stores-in-typescript-6474e012b81e

我也在使用 redux-saga,基本上我正在尝试创建一个类型安全的 takeEvery。

假设我有两个定义为接口的操作,如上面文章所建议的:

import { Action } from 'redux'

interface MyActionA extends Action {
  typeString: "MyActionA",
  payload: {
    // omitted
  }
}

interface MyActionB extends Action {
  typeString: "MyActionB",
  payload: {
    // omitted
  }
}

type MyActionBase =
  | MyActionA
  | MyActionB

是否有一些有效的方式来编写以下内容?:

function* typeSafeTakeEvery<ActionType extends MyActionBase>(saga: Function) {
  const typeString = ActionType.typeString; // <-- I don't know how to write this line
  yield takeEvery(typeString, function*(action: ActionType) {
    yield saga(action);
  });
}

对于这个泛型函数的任何给定实例,它知道 ActionType 的静态类型(MyActionA 或 MyActionB)并且它必须有一个 "typeString" 字段 "type" "MyActionA" 或 "MyActionB"。我想把这个 "type" 作为常量值,传递给实际的 takeEvery 函数。

我是不是离基地太远了?

要定义 value 'myValue' 而不是 type 'myValue',您可以使用 enum 而不是 interface:

enum MyEnum {
    myField = "myValue"
}

const value = MyEnum.myField;

更新

不编译的原因是因为 ActionType 是所谓的 type 参数,它是传递给 <...> 而不是(...),被称为参数,或者更简单地说,只是参数。

因为它是一个类型而不是一个值,所以 TypeScript 从编译的 JavaScript 输出中删除了它的定义,这就是为什么你会得到一个错误,它被用作一个值,即使它是一个类型。因此,当编译器运行时,它会留下对 ActionType 的未定义引用,该引用未在 JavaScript.

中的任何位置声明。

现在,为了解决你的问题,我仍然建议使用enum,并将actionType作为值参数传递,让ActionType类型参数推断其类型并使用它声明扩展 MyActionBase 的局部类型 MyAction,从而根据传递的字符串文字隐式选择 MyActionAMyActionB

import { Action } from 'redux'

enum MyActionType {
  MyActionA = 'MyActionA',
  MyActionB = 'MyActionB'
}

interface MyActionA extends Action {
  typeString: MyActionType.MyActionA,
  payload: {
    // omitted
  }
}

interface MyActionB extends Action {
  typeString: MyActionType.MyActionB,
  payload: {
    // omitted
  }
}

type MyActionBase =
  | MyActionA
  | MyActionB

function* typeSafeTakeEvery<ActionType extends MyActionType>(actionType: ActionType, saga: Function) {
  type MyAction = MyActionBase & { typeString: ActionType }

  yield takeEvery(actionType, function*(action: MyAction) {
    yield saga(action);
  });
}

// Usage

typeSafeTakeEvery(MyActionType.MyActionA, ...)