Open kaleidawave opened 1 month ago
Subtyping of
and the combination isn't too difficult. Might require some abstraction away from the type_is_subtype
function, a CompareToString
type etc
array slices are similar, but that is comparing slices of TypeId
s rather than char
s
This is the harder issue
For mapped types with as
, this requires pairing types during property lookup
export type Mapped<T> = {
[P in (keyof T & string) as `property_${P}`]: T[P]
}
function func(p: Mapped<{ a: string }>) {
p.property_a
}
Adding contributions to property lookup matching is quite complex.
instead maybe
export type Mapped<T> = {
[P in (keyof T & string) as `property_${P}`]: T[P]
}
// under synthesis it could be synthesised as the following. Where the `P` is moved to the RHS
export type Mapped<T> = {
[P in (keyof T & string) as `property_${keyof T & string}`]: T[Slice<P, 0, 8>]
}
Where Slice
is an internal type.
This could be implemented quite simply here because the root would be just P
type argument
Managed to get type_is_subtype
into key_matches
.
The next part is to try and get any matches through. There are two problems
get_property_unbound
needs to pass the slice through. To do this it could do through Logical::Implies
. However that requires changing either GenericChainLink
, GenericArguments
or ExplicitTypeRestrictions
. Don't like GenericArguments
or ExplicitTypeRestrictions
because that is PartiallyAppliedGenerics
and that is a lot simpler using TypeId
. Also that is perfectly fine because PartiallyAppliedGenerics
is created with &mut TypeStore
. GenericChainLink
is a little harder.&mut TypeStore
, so getting these arguments out needs a bit of work :/
Currently type pairing (/generic inference) is done during subtyping
For
During subtyping in the function invocation: the
5
argument is matched against theT
parameter.The current implementation first checks whether
5
meets the constraint ofT
. It isany
in this case and thus passes.Then it adds
(T, 5)
to the current state of subtyping, which effectively implies thatT=5
and during return substitution it substitutes anyT
references with literal type5
.This currently works very well. Additionally it:
This works when doing TypeId <=> TypeId comparison. The problem is for the following
"Hello Ben" extends `Hello ${infer T}` ? T : ...
. The string comparison isn't implemented yet. But when it does it needs to create a (T, "Ben") pair. The problem is that subtype cannot create new types (it doesn't have access to a&mut TypeStore
(only the non mutable reference).PropertyKey
(again not always a type can bePropertyKey::String
) so would have to create some type thing here.Possible implementation 1
Move the calculation into the type reference. Aka something like
infer T like `Hello ${string}` ? remove first 6 characters from T :
... and do the logic internally.Doesn't solve mapped type property key issue
Possible implementation 2
Make the paired result into a enum. Little bit scared that adds overhead to core item for the sake of TS consistency? Started on
enum PairRHS { Type(TypeId), PropertyKey(PropertyKey<'static>), SliceOf(...) }
in #146 but paused to get it merged. Maybe should have another go?