javascript - 指定 `keyof? 时拒绝 Typescript 泛型?

标签 javascript typescript

我有一个来自 RXJS 库的通用方法(此处简化):

function Subject<T>(t: T):T {
    return t;
}

我还有一个声明我的应用程序值的接口(interface)。 (可以添加 key )

interface IState { 
    key1: number;
    key2: string;
}

最后我有一个 Store适用于 IState与实际值的接口(interface),通过通用函数包装器(通用函数是 RXJS 主题的别名)

let Store  : IState=  Subject<IState>({  
    key1: void 0,
    key2: void 0,

})

好的,让我们添加 2 个从商店获取和设置的方法:

设置存储:

 function set<T>(name: keyof IState, statePart: T) {
        Store={
            ...Store,
            [name]: statePart 
        };

用法:set<string>("key1", "3");

这个函数工作正常,允许我只使用属于IState 的有效 key 。这里没有错误。

但是看着 Select方法:

(调用应该是这样的:)

let myVal:number = select<number>("key1");

方法如下:

function select<T>(k: keyof IState): T { 
    return <T>Store[k];  // <-- error here
}

Type 'string | number' cannot be converted to type 'T'. Type 'number' is not comparable to type 'T'.

问题:

这是为什么呢?如果我删除 keyof :

function select<T>(k): T { 
    return <T>Store[k];
}

然后它确实编译了,但是没有任何意义,StoreIstate 的类型和 Istate包含 Istate 的键

为什么没有 keyof 也能正常工作以及如何修复我的代码以便 select方法将强制只选择 Istate 的键?

ONLINE DEMO

最佳答案

问题是 k 可以是 IState 的任意键所以没有办法确保 Store[k] 是兼容的使用 T。我会将通用参数更改为键,并输入与字段类型相关的结果:

function select<K extends keyof IState>(k: K): IState[K] { 
    return Store[k];
}
let myVal  = select("key1"); // myval is number

set 也可以改进为没有明确的通用参数,并确保传递给 set 的值与字段类型兼容:

function set<K extends keyof IState>(name: K, statePart: IState[K]) {
    Store={
        ...Store,
        [name]: statePart 
    }
}

set("key1", 3);

编辑

如评论中所述,如果将鼠标悬停在调用上(至少在 vscode 中),您可以看到实际的推断类型:

enter image description here

如果你想保留显式类型参数,尽管我不推荐这样做,因为你很容易将字段类型和调用类型不匹配,你可以通过 any 使用类型断言:

function select3<T>(k: keyof IState): T { 
    return Store[k] as any;
}

关于javascript - 指定 `keyof? 时拒绝 Typescript 泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49572992/

相关文章:

javascript - 如何打破 promise 中的循环?

javascript - Jquery 切换多个 div

javascript - 创建 Q Promise 并稍后调用它

reactjs - React Onclick - 没有重载匹配这个调用

javascript - 升级到 WebStorm 2018.1 后,我在 this.setState 的 React Native 中得到了 "Protected member is not accessible"

javascript - 如何从 Javascript 函数将参数传递给 XSLT

javascript - 如何动态地将元素包裹在body内部

html - Angular5 mat-menu修改填充和宽度属性?

javascript - Javascript/Typescript 中对象数组的数据集

javascript - 如何处理 TypeScript 中内置对象的专有/自定义属性的警告