-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
More smart type inference #1212
Comments
What is the exact type of the |
@ahejlsberg let's move to more simple example, just: static getCurrentUser(): Result<CurrentUser, AuthError> {
var currentUser: models.CurrentUser;
return new Ok(currentUser)
} Compiler gives me the error:
It can infer |
Saying more formally, I suggest this: When we have some generic type with missed type arguments, we leave it as is until a first usage of this type in a context where these type arguments is known. Then we can substitute these types and use them as if they were pre-specified. |
If I understand the interface Result<T, E> {
andThen<U>(op: (x: T) => Result<U, E>): Result<U, E>;
...
} which implies that the interface Result<T, E> {
andThen<U, F>(op: (x: T) => Result<U, F>): Result<U, F>;
...
} You could then simply remove the return type annotation and rely on inference: static getApiToken() {
return this.getCurrentUser().andThen(user => new Ok<Token, AuthError>(user.token));
} |
@s-panferov I've left some feedback on your gist, have a look. |
@DanielRosenwasser thanks a lot! I will fix it! @ahejlsberg Result and Option are the types that replace null pointers in Rust. They are very helpful in TS too for using instead of
You are right, I can do it the way you suggested, but there are several disadvantages:
// Without type inference
function sqrt(x: number): Result<number, string> {
if (x < 0) {
return new Err<number, string>("Negative square root")
} else {
return new Ok<number, string>(Math.sqrt(x))
}
}
// With type inference
function sqrt(x: number): Result<number, string> {
if (x < 0) {
return new Err("Negative square root")
} else {
return new Ok(Math.sqrt(x))
}
} |
There are a lot of other cases where one can use this kind of type inference, e.g. declare function request<T>(url: string, options: any): Promise<T>;
/*
* Without inference
*/
// All is clear and readable, but we doubling the type annotations.
function loadCurrentUser(): Promise<CurrentUserReply> {
return request<CurrentUserReply>('/api/user/current', { /* .. */ })
}
// I have to remember the `request`'s return type all the time.
function loadCurrentUser() {
return request<CurrentUserReply>('/api/user/current', { /* .. */ })
}
/*
* With inference
*/
// The return type is clear and there are no doubling.
function loadCurrentUser(): Promise<CurrentUserReply> {
return request('/api/user/current', { /* .. */ })
} |
I have one more example with Maybe/Option type that shows that usage of generics will be simpler: function sayHello(name: Option<string>) {
if (name.isSome()) {
alert("Hello " + name.unwrap())
} else {
alert("Hello, Anonymous")
}
}
// I can't write this way
sayHello(new None());
// error TS2345: Argument of type 'None<{}>'
// is not assignable to parameter of type 'Option<string>'.
// I have to to write this:
sayHello(new None<string>()); There can be a very complex type (maybe generic) instead of |
Has there been any work done on this? It would be extremely useful to have this kind of inference as part of the language; I stumbled upon this exact problem tonight. |
Looking at this again, this is the same as #11152. |
I was trying to implement the Result type from Rust in TypeScript. Here is the result.
Everything works well but there is one thing that disappoints me:
In this code sample we can't just write
new Ok(user.token)
because TS can't inferAuthError
type from function's return type. Do you have any plans to add this functionality? Is think that it is not even a breaking change.The text was updated successfully, but these errors were encountered: