| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Anders Hejlsberg (@ahejlsberg) This is super close to a solution of #37181. Will it will allow us to do: function makeBox<T>(value: T) {
return { value };
};
// Can we do it or something similar? Currently doesn't compile :(
type MakeBox<T> = ReturnType<typeof makeBox<T>>
// As it now allows us to do (no generics though)
const stringMakeBox = makeBox<string>;
type MakeBox = ReturnType<typeof stringMakeBox>
// And even more relevant to support generics if we can now do:
type MakeBox = ReturnType<typeof makeBox<string>>Up to now makeBox<string> was illegal without calling it. But now that it is supported allowing typeof on it seems to fit nicely. |
Sorry, something went wrong.
|
Building the TypeScript playground for this PR would be better. |
Sorry, something went wrong.
Yes, you can indeed use that pattern to capture a generic return type of a generic function. This is something that previously wasn't possible. I'll update the PR description to include an example. |
Sorry, something went wrong.
|
Let's say we have a function f have a call signature f<T extends number, Q>() and a construct signature new f<T extends string>() What will this PR behave? They have different argument counts and even different different type constraints |
Sorry, something went wrong.
This works just fine: declare const f: {
<T extends number, Q>(): [T, Q];
new <T extends string>(): [T];
};
type T0 = typeof f<string>; // new () = [string]
type T1 = typeof f<number, string>; // () => [number, string]But an error occurs here: declare const g: {
<T extends number>(): [T];
new <T extends string>(): [T];
};
type T2 = typeof g<string>; // Error, type 'string' does not satisfy the constraint 'number' |
Sorry, something went wrong.
|
TypeScript Bot (@typescript-bot) test this |
Sorry, something went wrong.
|
Heya Anders Hejlsberg (@ahejlsberg), I'm starting to run the inline community code test suite on this PR at 8e466ba. Hold tight - I'll update this comment with the log link once the build has been queued. |
Sorry, something went wrong.
|
Did this feature get released in 4.7? Somehow when I try the example with ts version 4.7.4 (latest as of today) it complains in the editor. |
Sorry, something went wrong.
|
Yep, works in the playground - given that those inline error messages dont come from the official typescript extension (to my knowledge)- it's likely a local setup issue causing this |
Sorry, something went wrong.
|
It doesn't works on build-ins method 🤔 const cache = new WeakMap<
A,
ReturnType<typeof Object["getOwnPropertyDescriptors"]<A>> // error
>();
const a = { b: 1 }
type A = typeof a
const descMap = Object.getOwnPropertyDescriptors<A>(a) 'A' only refers to a type, but is being used as a value here.
Variable 'ReturnType' implicitly has an 'any' type.
Conversion of type '{ b: number; }' to type '<T>(o: T) => { [P in keyof T]: TypedPropertyDescriptor<T[P]>; } & { [x: string]: PropertyDescriptor; }' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
Type '{ b: number; }' provides no match for the signature '<T>(o: T): { [P in keyof T]: TypedPropertyDescriptor<T[P]>; } & { [x: string]: PropertyDescriptor; }'.
',' expected.
'>' expected.
Expression expected.
Expression expected.
Expression expected.
|
Sorry, something went wrong.
|
You cant use brackets, just qualified names: |
Sorry, something went wrong.
|
How to use this feature with overloaded functions ? declare function foo<T extends keyof HTMLElementTagNameMap>(arg: T): HTMLElementTagNameMap[T];
declare function foo<T extends HTMLElement>(arg: T): T;
type FirstFoo = typeof foo<"div">; // error
const f: ReturnType<FirstFoo> = foo("div");I couldn't get the code to work. The error message is Type 'string' does not satisfy the constraint 'HTMLElement'. The code works if I change the second foo to declare function foo<T extends HTMLElement, U>(arg: T, _unused: U): T;. |
Sorry, something went wrong.
|
Higher-order instantiation expressions don't resolve properly, as they weren't accounted for in the test baselines (see also issue #52035). declare function transform<
const A extends readonly any[],
F extends <
V extends A[number],
K extends keyof A,
>(value: V, index: K, array: A) => any
>(array: [...A], func: F): { [K in keyof A]: ReturnType<typeof func<A[K], K>> };
const $2 = transform(["object", "string", "number"], k => ({ type: k }));
// ^?
// Should be [{ type: "object" }, { type: "string" }, { type: "number" }], but is [any, any, any] |
Sorry, something went wrong.
Is there any issue tracking a design for a way we could do that? I've been trying to do something that I'd be able to accomplish if I could have a type like // type ApplyFn<Fn, Arg> = (some magic...)
type Applied = ApplyFn<<T>(value: T) => { value: T }, 1 | 2 | 3> // { value: 1 | 2 | 3 }Someone correct me if I'm wrong but it seems there's no way to do this for an arbitrary function. |
Sorry, something went wrong.
I don't believe there is. Instantiation expressions only work for values; you can't use a similar method in types. type Fn = <Arg>() => unknown
type ApplyFn<T, F extends Fn> = T extends unknown ? ReturnType<F<T>> : never
const f = <T>(): [T] => ({} as [T])
type t1 = ApplyFn<1 | 2, typeof f>The following (direct instead of the type parameter) works: type ApplyFn<T> = T extends unknown ? ReturnType<typeof f<T>> : never
type t1 = ApplyFn<1 | 2>
// ^? [1] | [2] |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
With this PR we implement Instantiation Expressions which provide the ability to specify type arguments for generic functions or generic constructors without actually calling them. For example:
Above, the instantiation expression makeBox<string> changes the type of makeBox from <T>(value: T) => { value: T } to the more specific type (value: string) => { value: string }. When emitted to JavaScript, instantiation expressions simply have the type arguments erased.
Instantiation expressions are particularly useful for creating specific instantiations of generic class constructors such as the ErrorMap above. Previously, this could only be accomplished with a type annotation or a redundant subclass:
The argument to the typeof type operator can now be an instantiation expression. For example:
A particularly useful pattern is to create generic type aliases for applications of typeof that reference type parameters in type instantiation expressions:
Notice how Box<T> captures the inferred return type of a generic function without loosing the generic type. This was previously not possible.
The type of an instantiation expression f<T> is determined as follows:
Note that an instantiation expression can be applied to any type, but that an error occurs if no call or construct signatures are present in the type. For example, an instantiation expression can be applied to a union that includes undefined:
Fixes #37181.
Fixes #40542.