访问typescript接口定义中定义的值

问题描述 投票:1回答:1

我是打字稿的新手,并且有一个关于它的问题,我似乎无法以可谷歌的方式构成。

假设我定义了这个接口:

interface MyInterface {
  myField: "myValue"
}

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

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

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

任何建议表示赞赏谢谢!

更新:

我想我需要提供更多信息。我正在尝试通过以下文章减少样板并在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”字段,其类型为“MyActionA”或“MyActionB”。我想将此“type”用作常量值,并将其传递给实际的takeEvery函数。

我离基地不远吗?

typescript redux interface redux-saga value-type
1个回答
1
投票

要定义值'myValue'而不是类型'myValue',您可以使用enum而不是interface

enum MyEnum {
    myField = "myValue"
}

const value = MyEnum.myField;

Update

不编译的原因是因为ActionType是所谓的类型参数,它是传递给<...>而不是(...)的任何东西,它们被称为值参数,或者更简单地说,只是参数。

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

现在,为了解决你的问题,我仍然建议使用enum,并传递actionType作为值参数,让ActionType类型参数推断其类型并使用它来声明扩展MyAction的本地类型MyActionBase,从而隐式地选择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, ...)
© www.soinside.com 2019 - 2024. All rights reserved.