-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Star-imported module should conform to the type of a string-indexed object #17622
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Interestingly, there doesn't seem to be a problem when using a value type of |
Since imports are inherently static, why not use import * as foo from './foo';
declare function bar(map: typeof foo): void; on a side note, this allows for some erroneous coding patterns such as // foo.ts
export let x = 1; // bar.ts
import * as foo from './foo';
function bar(map: typeof foo) {
map.x = 0; // WAT
}
map(foo); |
This was just a minimal repro. In practice, the function I'm trying to pass
Yeah, that's an oddity which should probably get its own bug report. |
It seems like when treating type Foo = {
readonly x: number
readonly y: number
}
let foo: Foo = {
x: 3,
y: 5,
} And in this case, function bar(map: { [k: string]: number }) {
// ...
}
bar(foo) type checks just fine. |
Indeed. With respect to reporting a bug about the mutable binding via an indirect reference to a module namespace object, the closest approximation is the |
I can't get the workaround from the OP to work with a JS library I'm using: // foo.d.ts
declare module "foo" {
class Bar { ... }
}
// app.ts
import * as Foo from "foo";
let f = {...Foo};
let bar = new f["Bar"]; // <-- Flagged with "no index signature" error I just need a way to pass around class constructors to dynamically choose a subclass at runtime. In my legacy (JS) code I did this with string-indexing into the module -- I'm not married to that solution in TS but it seems like it should work. |
Nevermind, it works regardless of the presence of |
I've got the wrong end of the stick here. What I'm trying to do is select a class declared in a module using the class name as a string. What I gave above as an example works without any workarounds, the problem is when I make the index parameter a variable instead of a literal. It's complaining that I can't index into the module with any old string, and I don't know how to constrain it such that the variable is forced to be a valid index key. I thought that was A better example: import * as Foo from "foo";
let b1 = new Foo["Bar"]; // I was wrong, no compiler error here
let k2: string = "Bar";
let b2 = new Foo[k2]; // compiler error, "has no index signature"
let k3: keyof Foo = "Bar"; // compiler error, "Cannot find name 'Foo'."
let b3 = new Foo[k3]; // I think this would work? Of course I can avoid this by just casting Foo to |
I see what the issue is now. import * as Foo from "foo";
let k3: keyof Foo = "Bar"; // compiler error, "Cannot find name 'Foo'." needs to be written as import * as Foo from "foo";
let k3: keyof typeof Foo = "Bar"; since For example // foo.d.ts
declare module "foo" {
type X = {id : number};
const X: X;
export = X;
} |
We should be able to apply the same treatment of inferred indexers to star-imports as we do for object literals, since (in theory) we know the entire set of members (because ES6 modules are immutable). |
TypeScript Version: 2.4.0 / nightly (2.5.0-dev.201xxxxx)
Suppose I have this module:
Conceptually this module represents a map of strings to numbers,
{ [k: string]: number }
, however if I try to use it directly as such I get a type error:Fortunately there is a workaround: I can simply spread and recompose the module to make it conform to the expected type:
However it'd be nice if the more straightforward approach just worked!
The text was updated successfully, but these errors were encountered: