I'm trying to use the updeep
library. A typical example of using updeep
is something like this:
var person = {
name: {
first: 'Jane',
last: 'West'
}
};
var result = u({ name: { first: 'Susan' } }, person);
The idea here is that result
will be a clone of person
but with the value of name.first
changed. You can imagine this function, u
, defined in TypeScript as:
function u<T>(changes: {}, obj: T): T { ... }
This captures the fact that the type of the second argument is also the return type of the function. But what it does not express is that changes
should be a super type of T
.
What I'd like is some type checking on the first argument. The point is that the values present in the changes
arguement should all be present in the T
type parameter and match the types of their counterparts there. Expressing this allows us to check the changes
argument to make sure it makes sense with respect to the type T
(i.e., is a super type of T
).
I'm not sure if this is possible in TypeScript. In languages like Java, you have the super
keyword and it can be used to describe constraints on type parameters.
While TypeScript doesn't allow it, something like this expresses what I would like:
function u<T extends U,U extends {}>(changes: U, obj: T): T { ... }
Does anybody have an suggestions on how to express this? It would be great to have a typesafe system for performing such transformations.
Thanks.
Using ?: with undefined as type definition While there are no errors with this interface definition, it is inferred the property value could undefined without explicitly defining the property type as undefined . In case the middleName property doesn't get a value, by default, its value will be undefined .
Type constraints are a very powerful way to supercharge your typescript codebases. For each generic type variable that you'd like to constrain, you would append the extends SomeTypeName to the definition. Example: const myFn = <T extends JsonValues, U extends FinancialData>() => {...}
TypeScript allows you to define multiple types. The terminology for this is union types and it allows you to define a variable as a string, or a number, or an array, or an object, etc. We can create union types by using the pipe symbol ( | ) between each type.
By passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.
This has been possible since TypeScript 2.1 with Partial<T>
The original problem would be solved with
function u<T>(changes: Partial<T>, obj: T): T { ... }
There's an open issue for something like this, called "Partial types" here: https://github.com/Microsoft/TypeScript/issues/4889
Facebook's Flow has a similar (but intentionally undocumented) $Shape<> type, which can be seen in the typings for React's setState().
So basically, no, there's no such feature that can do this automatically. However, you can kind of work around it by doing this manually:
interface IPartialPerson {
name?: {
first?: string;
last?: string;
};
someOptionalProperty?: string;
}
interface IPerson extends IPartialPerson {
name: {
first: string;
last: string;
};
}
Personally, I prefer to even avoid the latter part and just use optional properties as much as possible. Mandatory properties don't really protect you from anything; they're not non-nullable even though they look like it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With