-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Predefined conditional types #21847
Predefined conditional types #21847
Conversation
I think that should have been |
@tycho01 Right you are! Fixed. |
I wonder if it is possible to detect plain objects using the const plainObj = {foo: 'bar'}
const nonPlainObj = new Error()
IsPlainObject<typeof plainObj> // true
IsPlainObject<typeof nonPlainObj> // false
IsPlainObject<string> // false |
@AriaMinaei: for what it's worth, I'm not aware of any way we can do that so far. I think it comes down to getting a prototype, but as far as I know the type-level operators we have don't do much with JS prototypes. |
@tycho01 Thanks, now I know I shouldn't try more :) Here is my use-case though: export type Atomify<V> = {
'1':
V extends Array<infer T> ? ArrayAtom<Atomify<T>> :
V extends AbstractAtom<$IntentionalAny> ? V :
// following is commented out as I don't know how to detect plain objects in TS
// V extends {constructor: Function} ? BoxAtom<V> :
V extends object ? DictAtom<{[K in keyof V]: Atomify<V[K]>}> :
BoxAtom<V>
}[V extends number ? '1' : '1']
const atomifyDeep = <V extends {}>(jsValue: V): Atomify<V> => {
if (Array.isArray(jsValue)) {
return fromJSArray(jsValue)
} else if (isPlainObject(jsValue)) {
return fromJSObject(jsValue as $IntentionalAny)
} else if (jsValue instanceof AbstractAtom) {
return jsValue as $IntentionalAny
} else {
return fromJSPrimitive(jsValue)
}
}
const fromJSArray = (jsArray: $IntentionalAny): $IntentionalAny => {
return new ArrayAtom(jsArray.map(atomifyDeep))
}
const fromJSObject = (jsObject: {[key: string]: mixed}): $IntentionalAny => {
return new DictAtom(mapValues(jsObject, atomifyDeep))
}
const fromJSPrimitive = (jsPrimitive: mixed): $IntentionalAny => {
return new BoxAtom(jsPrimitive)
}
export default atomifyDeep This As you see, I used your |
Why are the "other" cases for ReturnType and InstanceType When would you want |
Awesome!! I get a few errors attempting to combine the use of type mapping with
|
Nevermind. WOW!! This works:
And so does this, to extract the return type out of the promise!! Amazing
|
I am playing around with this, and I would like to know a type mapper that resembles Flow Edit: I mean to say, that |
@michaeljota kinda like |
@tycho01 Almost! Thanks you so much! I test it, and is just class A {
a: string;
b: string;
}
class B {
a: string;
c: string;
}
type Diff<T, U> = Pick<T, Exclude<keyof T, keyof U>>;
type C = Diff<A, B>;
// C = { b: string; } Maybe I did not explain myself, but |
Any chance for Typescript to have a type mapper with this? Although the naming will be harder than usual. |
Is there a syntax that would work for this: // Doesn't work in 2.8
function f<T>(x: T): T { return x }
type R = ReturnType<typeof f<string>>; // = string |
it is not |
@mhegazy That's what I figured, thanks. Should I open a suggestion for allowing a type argument when a generic function is used in I know there is an open suggestion for allowing arbitrary expression in |
|
@mhegazy about the PR, do you plan to include |
No. we have avoided to use the names |
This PR adds several predefined conditional types to
lib.d.ts
:Exclude<T, U>
-- Exclude fromT
those types that are assignable toU
.Extract<T, U>
-- Extract fromT
those types that are assignable toU
.NonNullable<T>
-- Excludenull
andundefined
fromT
.ReturnType<T>
-- Obtain the return type of a function type.InstanceType<T>
-- Obtain the instance type of a constructor function type.Some examples:
The
Exclude
type is a proper implementation of theDiff
type suggested here #12215 (comment). We've used the nameExclude
to avoid breaking existing code that defines aDiff
, plus we feel that name better conveys the semantics of the type. We did not include theOmit<T, K>
type because it is trivially written asPick<T, Exclude<keyof T, K>>
.When applying
ReturnType<T>
andInstanceType<T>
to types with multiple call or construct signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types (this would require us to support typeof for arbitrary expressions, as suggested in #6606, or something similar).Fixes #19569.