pelotom / type-zoo Goto Github PK
View Code? Open in Web Editor NEWA menagerie of useful type operators for TypeScript
License: MIT License
A menagerie of useful type operators for TypeScript
License: MIT License
Hi, love the project!
Would you consider adding a type for overlapping string unions? It should be implementable directly based on the existing Diff
:
type Overlap<T extends string, U extends string> = Diff<T, Diff<T, U>>;
I'm not sure what would be the best name for the thing, but Overlap
seems descriptive and in line with the existing types in this library.
Best regards!
Any interest / reason to not want this type added? I can make a PR if so:
type ExtractStrict<T, U extends T> = T extends U ? T : never
context:
Seems like the TS team's reasoning for making their official Omit
non-strict included the fact that Extract
was also non-strict, which is something I just ran into wanting. Just like OmitStrict
, ExtractStrict
will get the compiler to help out during refactoring things like this, or to prevent typos in the string keys:
export type TSomeColorOptions = ExtractStrict<TColor, 'blue' | 'whitee'> // should error for typo
Using TypeScript 2.6.2, I have encountered an issue with Overwrite not being homomorphic.
Example:
export type Overwrite<T, U> = { [P in Diff<keyof T, keyof U>]: T[P] } & U;
interface A {
foo?: number;
bar?: number;
}
interface B {
bar?: string;
baz?: string;
}
type C = Overwrite<A, B>;
// error TS2322: Type '{ bar: string; }' is not assignable to type 'Overwrite<A, B>'.
// Type '{ bar: string; }' is not assignable to type '{ foo: number | undefined; }'.
// Property 'foo' is missing in type '{ bar: string; }'.
const c: C = {
bar: "hello"
};
I have solved this by rewriting Overwrite as:
export type Overwrite<T, U> = Omit<T, Diff<keyof T, Diff<keyof T, keyof U>>> & U;
Breaking it down:
Diff<keyof T, keyof U>
gives us all keys in T
that are not in U
. Let's call this NotInU
.Diff<keyof T, NotInU>
gives us all keys that are in both T
and U
. Let's call this InBoth
.Omit<T, InBoth>
gives us a type that contains only the properties that are unique to T
(omits all properties that also exist in U
).& U
to include ALL properties from Uhttps://gist.github.com/staltz/368866ea6b8a167fbdac58cddf79c1bf
Basically: Pick<>
only unpacks one level. It'd be nice to be able to pick deeper into nested objects!
As I mentioned in microsoft/TypeScript#25660 (comment) and in microsoft/TypeScript#21316 (comment)
without inversed check you got wrong result
declare function argTypes<F extends Function>(f: F): ParamTypes<F>
// $ExpectType []
argTypes(() => true); // Expected type to be: [] got: {}
// $ExpectType [string, boolean | undefined]
argTypes((x: string, y?: boolean) => true); // Expected type to be: [string, boolean | undefined] got: [string]
Hello. Someone just creating an overlapping library - https://github.com/danielpa9708/ts-types-utils - that has 3 types. 2 are duplicates:
Match
- https://github.com/danielpa9708/ts-types-utils#match looks quite useful
type FunctionProperties<T> = Match<T, Function>;
is easier to formulate than
type FunctionPropNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T];
type FunctionProperties<T> = Pick<T, FunctionPropNames<T>>;
Of course, just lifting it from https://github.com/danielpa9708/ts-types-utils wouldn't be cool, but maybe reach out to the author to consolidate?
Edit
It looks like @danielpa9708's ArgsType
could be an improvement on ParamTypes
- it looks to be able to work for any number of parameters, and ArgsType[N] === ParamN for any N....
Now that Typescript produces something assignable to string | number | symbol
for keyof T
, the definition of Required yields this error:
Type 'keyof T' does not satisfy the constraint 'string'.
Type 'string | number | symbol' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
46 [P in Purify<keyof T>]: NonNullable<T[P]>;
Projects using type-zoo could use the "keyofStringsOnly": true
compiler option as a workaround for the time being.
Longer term, the definition of Purify
could be updated to export type Purify<T extends string | number | symbol> = { [P in T]: T; }[T];
, however this is a breaking change for previous versions of TypeScript.
An alternative would be to declare something like type Purify2<O, T extends keyof O> = { [P in T]: T; }[T];
and have Required<T>
use that instead.
Thoughts? I can send a PR.
Context: Omit
is easier to implement now:
microsoft/TypeScript#12215 (comment)
Should we think about pulling that implementation in? What other types can be improved?
Can you please add a full text license file to this project?
https://help.github.com/articles/adding-a-license-to-a-repository/
export type Falsy = false | null | undefined | 0 | ''
export const isTruthy = <T>(val: T): val is Exclude<T, Falsy> => !!val
Given an object structure like:
interface A {
AA : string
BB : number
}
derive:
type C = {AA : string } | { BB : number}
This is how:
type Unionify<T> = {[K in keyof T]: Pick<T, K>}[keyof T];
type C = Unionify<A>
I'm not sure if it should be called Unionify or OneOf. Any idea on naming or other feedback appreciated.
Given:
interface A {
AA:number
}
derive:
interface B {
key : "AA",
value : number
}
Here's how:
export interface KeyValueify<T> {
key : keyof T
value : T[keyof T]
}
type B = KeyValueify<A>
Any ideas for better naming or any other feedback appreciated.
That way I can tell it vscode/prettier to just autoformat things the preferred way.
Could this be added?
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
Wanted to check here first before creating a pull request...
I'm starting to use this a fair bit for example when getting data from a datastore where all the values are strings. They don't necessarily fit the nicely typed structure I have for my model, but I don't want to have to explicitly write out a new type just for the version which is all strings coming back from the data store:
export type Monotype<T, U> = {[K in keyof T] : U}
Per https://twitter.com/OliverJAsh/status/935816602934829056
Add links to:
Explain the narrow goals of this project re. being a shim for proposed native/lib.d.ts
features.
The idea is that these types will hopefully make their way into the language proper, at which point you can simply stop importing them from type-zoo and be on your merry way.
Some of the types implemented here have been implemented in TypeScript's standard library, e.g.:
Since the versions implemented here are redundant, and in some cases more limited, I would suggest either aliasing them to the stdlib version, or documenting the supported TypeScript version and removing them.
Hi,
I'm fairly deep into my recent need to understand/learn Typescript's type system, and am using type-zoo
as well. I've run into an issue with Omit
that I don't understand, so I've made an example here to ask you about it:
here's the code (same as in the playground above):
// This is the definition of Omit from type-zoo
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Foo = {
x?: string
willOmitThis?: any
}
type Bar = {
y?: number
willOmitThis?: any
}
// ----------
// below, trying different ways to define a new Bar.
// in this version, we want to omit something and add something.
// ----------
type NewBarOmit = Omit<Bar, 'willOmitThis'> & {
addedToBar?: string[]
}
type NewBar = {
y?: number
addedToBar?: string[]
}
// -----------
// -----------
// here, trying different ways to define a new Foo.
// in this version, we want to omit something and add something.
// the `Omit` version doesn't cause the expected type-system error
// when a non-specified key is provided, the other version does.
// -----------
type NewFooOmit = Omit<Foo, 'willOmitThis'> & {
addedToFoo?: NewBar // or NewBarOmit, doesn't matter
}
type NewFoo = {
x?: string
addedToFoo?: NewBar // or NewBarOmit, doesn't matter
}
// -----------
/* `x: NewFoo` fails correctly, `x: NewFooOmit` doesn't fail, though it should? */
const x: NewFoo = {
addedToFoo: {
addedToBar: ['test'],
somethingElse: 'doesnt fail when x is of type NewFooOmit, why?',
},
// baz: 'fails in all cases when included, as expected',
}
I don't understand why the type system doesn't care that somethingElse
is not an allowed key of the object with type NewBar
if I defined NewBar
with Omit
.
Is this something about intersection types (the use of the &
after the Omit
) that I don't understand correctly? Or maybe something else, or an issue with Omit
perhaps? My understanding of intersection types is that the &
just combines two type definitions together to create a new type, but that doesn't seem to be correct.
(Sorry if this turns out to not be an question specific to type-zoo
and instead about TS, but I wasn't sure).
thanks!
Currently, if a union type is given to Omit
, the returned type does not correctly preserve the union type, e.g. this test fails:
declare const foo: Omit<{ shared: string; } & ({ x: boolean } | { y: string }), 'shared'>;
/* $ExpectType Pick<{
shared: string;
} & {
x: boolean;
}, "x"> | Pick<{
shared: string;
} & {
y: string;
}, "y"> */
foo;
foo
instead has type
Pick<({
shared: string;
} & {
x: boolean;
}) | ({
shared: string;
} & {
y: string;
}), never>
We can use conditional types to fix this:
export type Omit<T, K extends keyof any> = T extends any ? Pick<T, Exclude<keyof T, K>> : never;
microsoft/TypeScript#12215 (comment)
We might also want to apply this fix to some of the other helpers?
Because of TypeScript 2.8 Conditional Types, we can now do the following:
type Param0<Func> = Func extends (a: infer T, ...args: any[]) => any
? T
: never;
type T0 = Param0<() => void>; // {}
type T1 = Param0<(a: number) => void>; // number
type T2 = Param0<(a: string[]) => void>; // string[]
Issue for discussion!
Questions:
See also ReturnType<Func>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.