我有以下功能:
change(key: keyof McuParams, dispatch: Function) {
/** Body removed for brevity */
}
当我调用该函数时......
this.change(VARIABLE_FROM_MY_API, this.props.dispatch)
...我(可以理解)得到以下错误:
Argument of type 'string' is not assignable to parameter of type '"foo" | "bar"'
这是有道理的,因为编译器无法知道我的API在编译时发送了什么。但是,user defined type guards有时可用于在运行时推断类型信息,并通过条件将该信息传递给编译器。
当keyof
仅被定义为类型(而不是数组)时,是否可以为keyOf foo
字符串类型(例如foo
)编写用户定义的类型保护)?如果是这样,怎么样?
答案 0 :(得分:2)
以下是一个例子:
interface McuParams {
foo, bar, baz;
}
function change(key: keyof McuParams, dispatch: Function) {
}
function isKeyOfMcuParams(x: string): x is keyof McuParams {
switch (x) {
case 'foo':
case 'bar':
case 'baz':
return true;
default:
return false;
}
}
function doSomething() {
const VAR_FROM_API = <string>'qua';
if (!isKeyOfMcuParams(VAR_FROM_API)) return;
change(VAR_FROM_API, () => { });
}
在doSomething
中,您可以使用您喜欢的任何控制流程块,而不是return
(例如if
或throw
等)。
答案 1 :(得分:1)
尝试以下方法:
enum mcuParams { foo, bar };
type McuParams = keyof typeof mcuParams;
function isMcuParams(value: string) : value is McuParams {
return mcuParams.hasOwnProperty(value);
}
function change(key: McuParams) {
//do something
}
let someString = 'something';
if (isMcuParams(someString)) {
change(someString);
}
更新:
我上面写的例子假设我们已经知道McuParams('foo'或'bar')的可能值。以下示例不做任何假设。我测试了它,它按预期工作。每次运行代码时,都会根据随机生成的值得到不同的响应。
function getAllowedKeys() {
//get keys from somewhere. here, I generated 2 random strings just for the sake of simplicity
let randomString1 = String(Math.round(Math.random())); //0 or 1
let randomString2 = String(Math.round(Math.random())); //0 or 1
return Promise.resolve([randomString1, randomString2]);
}
function getKeyToBeTested() {
//same as in 'getAllowedKeys'
let randomString = String(Math.round(Math.random())); //0 or 1
return Promise.resolve(randomString);
}
Promise.all([getAllowedKeys(), getKeyToBeTested()]).then((results) => {
let allowedKeys: string[] = results[0];
let keyTobeTested: string = results[1]; //'0' or '1'
let mcuParams = {};
for (let entry of results[0]) { //create dictionary dynamically
mcuParams[entry] = ''; //the value assigned is indiferent
}
//create type dynamically. in this example, it could be '0', '1' or '0' | '1'
type McuParams = keyof typeof mcuParams;
//create Type Guard based on allowedKeys fetched from somewhere
function isMcuParams(value:string) : value is McuParams {
return mcuParams.hasOwnProperty(value);
}
function change(key: McuParams) {
//do something
alert('change function executed: [' + allowedKeys.toString() + '] - ' + keyTobeTested);
}
if (isMcuParams(keyTobeTested)) {
change(keyTobeTested);
}
else {
alert('change function not executed: [' + allowedKeys.toString() + '] - ' + keyTobeTested);
}
});
答案 2 :(得分:0)
更新:
根据我提供的最新理解和您提供的背景信息,这是与您的用例相关的代码段吗?如果是这样,它对我来说很好。
interface McuParams {
foo: string;
bar: string;
};
function change(key: keyof McuParams, dispatch: Function) {
if (typeof key === 'foo') {
console.log('call foo()');
} else if (typeof key === 'bar') {
console.log('call bar()');
}
}
function callback(data) {
change(data, this.props.dispatch)
}