访问在打字稿接口定义中定义的值
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
,从而根据传递的字符串文字隐式选择 MyActionA
或 MyActionB
。
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, ...)
我是打字稿的新手,有一个问题我似乎无法以 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
,从而根据传递的字符串文字隐式选择 MyActionA
或 MyActionB
。
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, ...)