Skip to content
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

error in type inference when using keyof #15099

Closed
dardino opened this issue Apr 10, 2017 · 5 comments
Closed

error in type inference when using keyof #15099

dardino opened this issue Apr 10, 2017 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@dardino
Copy link

dardino commented Apr 10, 2017

TypeScript Version: 2.2.1

Code

interface TestObj {
	P1: string;
	P2: number;
} 
function register<T, K extends keyof T>(pName: K, callback: (data: T[K]) => void): void { }
register<TestObj>("P1", data => {
   // data is string because "P1" is string
});

Expected behavior:
compile with no errors.
Actual behavior:
compile error:
playground
the only way I found is to write P1 "twice":

register<TestObj, "P1">("P1", (data) => { }); // compile ok, data type is correctly 'string'

but in my honest opinion this is not so good.

@dardino dardino changed the title Inference in keyof error in type inference when using keyof Apr 10, 2017
@jinder
Copy link

jinder commented Apr 10, 2017

@dardino does function test<T>(pName: keyof T, callback: (data: T[keyof T]) => void): void { } work for you?

@dardino
Copy link
Author

dardino commented Apr 11, 2017

No.
Your example don't cover my case:

interface IMsg1 { p1: string; }
interface IMsg2 { pn: number; }
interface IMsg3 { pd: Date; }
interface IMessages { // interface that exposes all available messages
	M1: IMsg1;
	M2: IMsg2;
	M3: IMsg3;
}
// writing this:
function Register<T>(pname: keyof T, c: (m: T[keyof T]) => void): void {
}
// and then calling this:
Register<IMessages>("M1", (msg) => {
   // in this closure the var "msg" has three types: IMsg1 | IMsg2 | IMsg3
   // but I want only the type corresponding to "M1" that is IMsg1
});

to achieve this goal I need to write this:

function Register<T, P extends keyof T>(pname: P, c: (m: T[P]) => void): void {
}

Register<IMessages, "M1">("M1", (msg) => {
   // in this closure msg type is correctly IMsg1.
});

@dmichon-msft
Copy link
Contributor

The error is coming from the generic parameters. If you do:

declare function test<T, K extends keyof T>(obj: T, pName: K, callback: (data: T[K]) => void): void;
let obj: TestObj;
test(obj, 'P1', data => {
    // 'data' is inferred as 'string' here
});

TypeScript (as of the version in the playground) supports either specifying all generic parameters or none of them.

@dardino
Copy link
Author

dardino commented Apr 18, 2017

In your example you need to give an object as first parameter.
I don't want this. I only want a constraint check between the 1st argument (message key) and 2nd argument (message body), another case:

// My framework defined method (framework doesn't know the available frames and their commands)
function SendCommandToIFrame<T, P extends keyof T>(key: P, msg: T[P]) {
	window.postMessage({
		command: key,
		body: msg
	}, "*");
}

// region User owned file:
type ImportCommand = { Name: string, Type: string };
type ExportCommand = { OriginalName: string, Type: string };

type AvailableIFrames = { Iframe1: ImportCommand, Iframe2: ExportCommand };

SendCommandToIFrame<AvailableIFrames, "Iframe1">("Iframe1", {
	Name: "prova.wav",
	Type: "audio/wav"
});

SendCommandToIFrame<AvailableIFrames, "Iframe2">("Iframe2", {
	OriginalName: "prova.wav",
	Type: "audio/wav"
});

@mhegazy
Copy link
Contributor

mhegazy commented Apr 19, 2017

looks like a duplicate of #10571

@mhegazy mhegazy added the Duplicate An existing issue was already created label Apr 19, 2017
@dardino dardino closed this as completed Apr 21, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants