Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Checked subset typing in TypeScript
// Imagine you want to explicitly define which members of a public API
// interface your implementation actually uses. Example: you implement
// a web extension, but only use a few of the members on the argument
// to the onHeadersReceived handler. Explicitly typing this is useful
// when creating mocks in your unit tests.
//
// Here's now you could do it:
// Inverse keyword of "extends": ensure every member of type Sub exists
// on type Super.
function EnsureSubsetType<Sub, Super extends Sub>() {}
// Explicit list of fields we use from the webrequest API.
interface ResponseDetails {
url: string;
requestId: string;
tabId: number;
responseHeaders?: chrome.webRequest.HttpHeader[];
}
EnsureSubsetType<ResponseDetails, chrome.webRequest.WebResponseDetails>(); // this does actual checking
export class MyPlugin {
// ...
onHeadersReceived(details: ResponseDetails) {
// use only the fields on details which you defined above
}
// ...
}
// Try adding a random field in the struct above and see the type
// checking line fail.
//
// This makes unit testing MyPlugin easier. Without it, if I call the
// onHeadersReceived method in my unit test, I'm not sure which fields
// I _actually_ need to mock. Now the typechecker tells me. Without it,
// I'd be mocking all kinds of unnecessary detailed fields which my
// plugin doesn't actually need.
//
// Limitation: this does not work for optional members! the responseHeaders field
// above could be called anything or have any type and it would pass the typecheck.
@codeandcats

This comment has been minimized.

Copy link

codeandcats commented Mar 24, 2017

Neat trick 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.