-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Support explicit type compatibility assertion #16605
Comments
Even better: make sure that incompatible types will raise a type error class MyEvent<A> {
readonly _A: A
constructor(readonly name: string) {}
}
type Handler<A> = (a: A) => void
declare class MyEventEmitter {
on<A>(event: MyEvent<A>): (handler: Handler<A>) => void
emit<A>(event: MyEvent<A>): (a: A) => void
}
interface SomeEventData {
foo: number
bar: string
}
const emitter = new MyEventEmitter()
const someEvent = new MyEvent<SomeEventData>('some-event')
emitter.emit(someEvent)({}) // error
emitter.emit(someEvent)({ foo: 'a' }) // error
emitter.emit(someEvent)({ foo: 1, bar: 's' }) // ok
emitter.on(someEvent)(() => {}) // ok
emitter.on(someEvent)((foo: number) => {}) // error
emitter.on(someEvent)(foo => {}) // ok
emitter.on(someEvent)((foo: SomeEventData) => {}) // ok |
@gcanti Looks nice (sharing data type between |
Yeah, maybe a branded type instead of a class? type MyEvent<A> = string & { _A: A } // branded type, the runtime representation is still a string
function createEvent<A>(name: string): MyEvent<A> {
return name as any
}
const someEvent = createEvent<SomeEventData>('some-event') |
I cannot find other discussion on this, but I have also thought it would be useful to have a type-assertion like operator that doesn't actually coerce the type of the expression. This operator:
For example: interface Foo {
bar(x: string): void;
}
// 'x' has type
//
// {
// bar(a: string): void,
// baz(): number
// }
//
const x = {
bar(a) {
console.log(a.toLowerCase());
}
baz() {
return 100;
}
} compatibleWith Foo; |
@gcanti Nice try, but it would still be weird working with existing event emitters. :( |
migrated from #20188 in my code i often use, let's call them, type invariants assertions: function mustBe<T>(_: () => T): void {}
interface A {
isThat: true;
text: string;
}
interface B {
isThat: false;
value: number;
}
type C = A | B;
declare const C: C;
mustBe<true>(() => C.isThat); // <-- type error as expected now i wish i could do type invariant assertions without emitting any useless code, making it a zero cost abstraction: makesure C.isThat sameas true; where few more examples makesure typeof c.isThat subtypeof boolean
makesure MyClass subtypeof BaseClass
// ... |
c.f. #7481 |
Sometimes we may want to explicitly assert whether the type of a expression is compatible with a certain type, but type assertion does not satisfy the type safety we want:
The behavior is desired but it would be nice if we have an elegant way for more secure type checking instead of:
E.g.:
The text was updated successfully, but these errors were encountered: