i can't compile this kind of thing:
type F<A> = (a:A)=>A;
class CLAZZ<S extends { [k: string]: any }, K extends keyof S = keyof S>{
constructor(a:S){
this._o=a;
}
_o:S;
set(k:K, f:F<S[K]>){
f(this._o[k]);
}
}
type O = {
pippo: number,
pluto: string | null,
paperino: {[k:string]:boolean}
}
let o = new CLAZZ<O>({"paperino":{}, pluto:null, pippo:1});
o.set("paperino", (paperino)=>({...paperino, "ciccio":true}))
the last line give this error:
Spread types may only be created from object types.
this because the paperino argument is inferred as
(parameter) paperino: string | number | { [k: string]: boolean; } | null
and not just as
{ [k: string]: boolean; }
as i'm expecting...
also forcing the parameter type give me an error
o.set("paperino", (paperino: {[k:string]:boolean})=>({...paperino,"ciccio":true}))
Argument of type '(paperino: { [k: string]: boolean; }) => { ciccio: true; }' is not assignable to parameter of type 'F<string | number | { [k: string]: boolean; } | null>'. Types of parameters 'paperino' and 'a' are incompatible. Type 'string | number | { [k: string]: boolean; } | null' is not assignable to type '{ [k: string]: boolean; }'. Type 'null' is not assignable to type '{ [k: string]: boolean; }'.
any solution other than... "any"?
set
, if you want types to be narrowed when you call a function, you can make it generic as well, something likeset<K1 extends K>(k:K1, f:F<S[K1]>)
should do. (CLAZZ<O>
that just looks a bit misspelled :D ) – Nadia Chibrikova