Closed
Description
TypeScript Version: 3.1.0-dev.201xxxxx
Search Terms:
- keyof generic intersection
Code
Helper types:
// Extract keys whose values match a condition
type Filter<T, Cond> = {
[K in keyof T]: T[K] extends Cond ? K : never
}[keyof T]
type Fun = (...args: any[]) => any
// Extract method names from an object type
type Methods<T> = Filter<T, Fun>
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Prefer<T, U> = U & Omit<T, (keyof T) & (keyof U)>
Implementation:
interface Events {
foo(): void
bar: number
}
class Foo<T, U = T & Events> {
hey(arg: Methods<U>): void { }
duk(arg: Filter<U, Fun>): void { }
wat(arg: Methods<T & Events>): void { }
how(arg: Filter<T & Events, Fun>): void { }
foo(arg: Methods<Prefer<T, Events>>): void { }
who(arg: Filter<Prefer<T, Events>, Fun>): void { }
ugh(arg: keyof U): void { }
bar(arg: keyof Prefer<T, Events>): void { }
tau(arg: keyof (T & Events)): void { }
test() {
this.hey('foo') // ✕
this.duk('foo') // ✕
this.wat('foo') // ✕
this.how('foo') // ✕
this.foo('foo') // ✕
this.who('foo') // ✕
this.ugh('foo') // ✕
this.bar('foo') // OK ("foo" | "bar" | Exclude<keyof T, ("foo" & keyof T) | ("bar" & keyof T)>)
this.tau('foo') // OK (keyof T | "foo" | "bar")
}
}
Expected behavior:
No errors
Actual behavior:
Unexpected errors
Playground Link: https://goo.gl/X4KcBN