-
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
Should mapped types where the result is never filter keys? #23199
Comments
Technically a type with at least one property of type that said, the way the compiler defers getting the types of properties. this is the only way really to reason about structural types and recursive types without chocking. so when an type is created, the compiler only knows about its properties, and not their types. it only compute the property types when it needs to. needing to do this filtering means that when a type is created the compiler needs to figure out its property types to know whether to add the property or not. You can achieve what you were looking for by first filtering the keys, then creating a mapped type from the filtered keys.. e.g.: type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
type Apples = {
[Q in FilteredKeys<Fruits, Apple>]: Fruits[Q]
}; |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
Nice! Has the same issue and this solves it. Thanks! |
unfortunately this does not seem to preserve optional members: type SubtractKeys<T, U> = { [K in keyof T]: K extends keyof U ? never : K }[keyof T]
type Subtract<T, U> = { [K in SubtractKeys<T, U>]: T[K] }
type Foo = {
a: string
b?: string
}
type Bar = {
a: string
}
type FooWithoutBar = Subtract<Foo, Bar>
// {
// b: string | undefined
// } there is a difference between |
also it doesn't work with generics at all interface ISimpleString {
value: string;
}
interface ISimpleNumber{
value: number;
}
interface ModelPropertiesDeclaration {
[key: string]: ISimpleString
}
type IModelType<P extends ModelPropertiesDeclaration> = {}
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
// =====
// Test
// =====
interface TestModel {
label: ISimpleString,
age: ISimpleNumber
};
type BuildFromPropsC = IModelType<{
[K in FilteredKeys<TestModel, ISimpleString>]: TestModel[K] // <-- this works
}>
type BuildFromProps<P extends TestModel> = IModelType<{
[K in FilteredKeys<P, ISimpleString>]: P[K] // <-- doesn't work
}>; |
Hi, here is another example where
does not work. |
TypeScript 4.1 - Key RemappingTypescript 4.1 has a new feature Key Remapping. You can now do the following:
And yes, if you produce |
I am not sure that this is a bug but it did behave in a way that I did not expect which is why I filed a new issue. If this is not a bug it should probably be closed and continued in earlier issues like #17678
TypeScript Version: 2.8.1
Search Terms:
Mapped types, never, filter, conditional types, Exclude, Omit, Pick
Code
Expected behavior:
I expected Apples to have type
Actual behavior:
Apples have the type
Having an object with a never key is quite strange to me. How would that object ever be created?
Playground Link: http://www.typescriptlang.org/play/#src=%0D%0Atype%20Fruit%20%3D%20%7B%20name%3A%20string%20%7D%3B%0D%0Atype%20Apple%20%3D%20Fruit%20%26%20%7B%20cultivar%3A%20string%20%7D%3B%0D%0A%0D%0Atype%20Fruits%20%3D%20%7B%0D%0A%20%20banana%3A%20Fruit%3B%0D%0A%20%20alice%3A%20Apple%3B%0D%0A%20%20gala%3A%20Apple%3B%0D%0A%7D%3B%0D%0A%0D%0Atype%20Apples%20%3D%20%7B%0D%0A%20%20%5BT%20in%20keyof%20Fruits%5D%3A%20Fruits%5BT%5D%20extends%20Apple%20%3F%20Fruits%5BT%5D%20%3A%20never%0D%0A%7D%3B%0D%0A
Related Issues:
If this have worked as expected #17678 would be already be supported. That issue is marked as a duplicate and linked to #12424 and #17636 but I am not sure I see the direct relation there to be honest.
The text was updated successfully, but these errors were encountered: