admin管理员组文章数量:1025235
Typescript error
(method) R.Static.prop(p: string): (obj: Record) => T (+3 overloads)
Returns a function that when supplied an object returns the indicated property of that object, if it exists.
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
The code:
// Changes value of key in object without mutation
export const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
How this function is used
interface IMyObj {
position: number;
price: number;
value: number;
}
const myObj: IMyObj = {
position: 1,
price: 100,
value: 100
}
const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
const newObj = R.set(updateKey('value'), 200, myObj);
console.log('newObj', newObj); // {"position":1,"price":100,"value":200}
In my actual app this is what the signature of my IAsset objects look like:
export interface IAsset {
[key: string]: string | number | undefined | boolean;
availableSupply?: string;
currency: string;
exchange: string;
exchange_base?: string;
marketCap: number;
name: string;
percentage?: number;
price: number;
position?: number;
value?: number;
inWatchlist?: boolean;
}
// Changes value of key in object without mutation
export const updateKey = (key: IAsset[string]) => {
if (key) {
return R.lens(R.prop(key), R.assoc(key));
}
}
However it still produces this Typescript warning:
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
Also side note, Typescript is killing the fun of beautiful small 1-line Ramda functional functions.
Typescript error
(method) R.Static.prop(p: string): (obj: Record) => T (+3 overloads)
Returns a function that when supplied an object returns the indicated property of that object, if it exists.
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
The code:
https://ramdajs./docs/#lens
// Changes value of key in object without mutation
export const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
How this function is used
interface IMyObj {
position: number;
price: number;
value: number;
}
const myObj: IMyObj = {
position: 1,
price: 100,
value: 100
}
const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
const newObj = R.set(updateKey('value'), 200, myObj);
console.log('newObj', newObj); // {"position":1,"price":100,"value":200}
In my actual app this is what the signature of my IAsset objects look like:
export interface IAsset {
[key: string]: string | number | undefined | boolean;
availableSupply?: string;
currency: string;
exchange: string;
exchange_base?: string;
marketCap: number;
name: string;
percentage?: number;
price: number;
position?: number;
value?: number;
inWatchlist?: boolean;
}
// Changes value of key in object without mutation
export const updateKey = (key: IAsset[string]) => {
if (key) {
return R.lens(R.prop(key), R.assoc(key));
}
}
However it still produces this Typescript warning:
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
Also side note, Typescript is killing the fun of beautiful small 1-line Ramda functional functions.
Share Improve this question edited Mar 12, 2019 at 21:49 Leon Gaban asked Mar 12, 2019 at 15:51 Leon GabanLeon Gaban 39.1k123 gold badges349 silver badges551 bronze badges 3-
from what place came type
'(s: {}) => {}
? – Przemyslaw Jan Beigert Commented Mar 12, 2019 at 16:07 -
@PrzemyslawPietrzak I believe because Typescript knows I'm changing an Object's Record or key, and R.prop works on Objects, and the updateKey function takes in an Object as well as a new value to change.
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'.
– Leon Gaban Commented Mar 12, 2019 at 16:24 - 2 As to "Typescript is killing the fun of beautiful small 1-line Ramda functional functions", I've heard a lot of this over the last two years. As a Ramda developer, I have not found it a core concern; we're writing a JS library and want to make it as pleasant as we can for JS developers. We'd love it if it worked well with Typescript, but we won't sacrifice our JS API to that. And as yet it seems that TS doesn't really support the full range of constructs we use. I'd love to see that change, but I'm not holding my breath. – Scott Sauyet Commented Mar 12, 2019 at 17:42
1 Answer
Reset to default 2For your original question:
I'm no expert in Ramda, so perhaps I'm missing something with how these types are used, but it looks like you can get rid of the type errors by making updateKey
generic:
const updateKey = <T, K extends string>(key: K) => R.lens(R.prop<K, T>(key), R.assoc(key));
Note that the type inference here won't be great. If you hover over updateKey("value")
, the inferred type will be <{}, "value">(key: "value") => Lens
, so you may need explicitly specify type arguments in certain scenarios.
For your updated question:
There's definitely something I'm missing. Your interface for IAsset
doesn't support numeric keys—only strings. So there should be no need to worry anything other than strings, however, let's assume for the sake of argument that you also want to handle numeric or symbolic keys.
If you look at @types/ramda
, the single-parameter overloads of prop
and assoc
only accept strings:
/**
* Returns a function that when supplied an object returns the indicated property of that object, if it exists.
*/
prop<T>(__: Placeholder, obj: T): <P extends keyof T>(p: P) => T[P];
prop<P extends keyof T, T>(p: P, obj: T): T[P];
prop<P extends string>(p: P): <T>(obj: Record<P, T>) => T;
prop<P extends string, T>(p: P): (obj: Record<P, T>) => T;
/**
* Makes a shallow clone of an object, setting or overriding the specified property with the given value.
*/
assoc<T, U>(__: Placeholder, val: T, obj: U): <K extends string>(prop: K) => Record<K, T> & U;
assoc<U, K extends string>(prop: K, __: Placeholder, obj: U): <T>(val: T) => Record<K, T> & U;
assoc<T, U, K extends string>(prop: K, val: T, obj: U): Record<K, T> & U;
assoc<T, K extends string>(prop: K, val: T): <U>(obj: U) => Record<K, T> & U;
assoc<K extends string>(prop: K): <T, U>(val: T, obj: U) => Record<K, T> & U;
I'm not sure, but I believe this is an oversight on the @types/ramda
project. You could enhance the type definition through declaration merging in this way:
interface Static {
prop<P extends keyof T, T>(p: P): (obj: Record<P, T>) => T;
assoc<K extends keyof T, T>(prop: K): <T, U>(val: T, obj: U) => Record<K, T> & U;
}
And then type your updateKey
method like this, without the need for separate blocks to handle different key types:
const updateKey = <K extends keyof IAsset>(key: K) => R.lens(R.prop<K, IAsset>(key), R.assoc<K, IAsset>(key));
Typescript error
(method) R.Static.prop(p: string): (obj: Record) => T (+3 overloads)
Returns a function that when supplied an object returns the indicated property of that object, if it exists.
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
The code:
// Changes value of key in object without mutation
export const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
How this function is used
interface IMyObj {
position: number;
price: number;
value: number;
}
const myObj: IMyObj = {
position: 1,
price: 100,
value: 100
}
const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
const newObj = R.set(updateKey('value'), 200, myObj);
console.log('newObj', newObj); // {"position":1,"price":100,"value":200}
In my actual app this is what the signature of my IAsset objects look like:
export interface IAsset {
[key: string]: string | number | undefined | boolean;
availableSupply?: string;
currency: string;
exchange: string;
exchange_base?: string;
marketCap: number;
name: string;
percentage?: number;
price: number;
position?: number;
value?: number;
inWatchlist?: boolean;
}
// Changes value of key in object without mutation
export const updateKey = (key: IAsset[string]) => {
if (key) {
return R.lens(R.prop(key), R.assoc(key));
}
}
However it still produces this Typescript warning:
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
Also side note, Typescript is killing the fun of beautiful small 1-line Ramda functional functions.
Typescript error
(method) R.Static.prop(p: string): (obj: Record) => T (+3 overloads)
Returns a function that when supplied an object returns the indicated property of that object, if it exists.
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
The code:
https://ramdajs./docs/#lens
// Changes value of key in object without mutation
export const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
How this function is used
interface IMyObj {
position: number;
price: number;
value: number;
}
const myObj: IMyObj = {
position: 1,
price: 100,
value: 100
}
const updateKey = (key: string) => R.lens(R.prop(key), R.assoc(key));
const newObj = R.set(updateKey('value'), 200, myObj);
console.log('newObj', newObj); // {"position":1,"price":100,"value":200}
In my actual app this is what the signature of my IAsset objects look like:
export interface IAsset {
[key: string]: string | number | undefined | boolean;
availableSupply?: string;
currency: string;
exchange: string;
exchange_base?: string;
marketCap: number;
name: string;
percentage?: number;
price: number;
position?: number;
value?: number;
inWatchlist?: boolean;
}
// Changes value of key in object without mutation
export const updateKey = (key: IAsset[string]) => {
if (key) {
return R.lens(R.prop(key), R.assoc(key));
}
}
However it still produces this Typescript warning:
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'. Types of parameters 'obj' and 's' are inpatible. Type '{}' is not assignable to type 'Record'. Index signature is missing in type '{}'.ts(2345)
Also side note, Typescript is killing the fun of beautiful small 1-line Ramda functional functions.
Share Improve this question edited Mar 12, 2019 at 21:49 Leon Gaban asked Mar 12, 2019 at 15:51 Leon GabanLeon Gaban 39.1k123 gold badges349 silver badges551 bronze badges 3-
from what place came type
'(s: {}) => {}
? – Przemyslaw Jan Beigert Commented Mar 12, 2019 at 16:07 -
@PrzemyslawPietrzak I believe because Typescript knows I'm changing an Object's Record or key, and R.prop works on Objects, and the updateKey function takes in an Object as well as a new value to change.
Argument of type '(obj: Record) => T' is not assignable to parameter of type '(s: {}) => {}'.
– Leon Gaban Commented Mar 12, 2019 at 16:24 - 2 As to "Typescript is killing the fun of beautiful small 1-line Ramda functional functions", I've heard a lot of this over the last two years. As a Ramda developer, I have not found it a core concern; we're writing a JS library and want to make it as pleasant as we can for JS developers. We'd love it if it worked well with Typescript, but we won't sacrifice our JS API to that. And as yet it seems that TS doesn't really support the full range of constructs we use. I'd love to see that change, but I'm not holding my breath. – Scott Sauyet Commented Mar 12, 2019 at 17:42
1 Answer
Reset to default 2For your original question:
I'm no expert in Ramda, so perhaps I'm missing something with how these types are used, but it looks like you can get rid of the type errors by making updateKey
generic:
const updateKey = <T, K extends string>(key: K) => R.lens(R.prop<K, T>(key), R.assoc(key));
Note that the type inference here won't be great. If you hover over updateKey("value")
, the inferred type will be <{}, "value">(key: "value") => Lens
, so you may need explicitly specify type arguments in certain scenarios.
For your updated question:
There's definitely something I'm missing. Your interface for IAsset
doesn't support numeric keys—only strings. So there should be no need to worry anything other than strings, however, let's assume for the sake of argument that you also want to handle numeric or symbolic keys.
If you look at @types/ramda
, the single-parameter overloads of prop
and assoc
only accept strings:
/**
* Returns a function that when supplied an object returns the indicated property of that object, if it exists.
*/
prop<T>(__: Placeholder, obj: T): <P extends keyof T>(p: P) => T[P];
prop<P extends keyof T, T>(p: P, obj: T): T[P];
prop<P extends string>(p: P): <T>(obj: Record<P, T>) => T;
prop<P extends string, T>(p: P): (obj: Record<P, T>) => T;
/**
* Makes a shallow clone of an object, setting or overriding the specified property with the given value.
*/
assoc<T, U>(__: Placeholder, val: T, obj: U): <K extends string>(prop: K) => Record<K, T> & U;
assoc<U, K extends string>(prop: K, __: Placeholder, obj: U): <T>(val: T) => Record<K, T> & U;
assoc<T, U, K extends string>(prop: K, val: T, obj: U): Record<K, T> & U;
assoc<T, K extends string>(prop: K, val: T): <U>(obj: U) => Record<K, T> & U;
assoc<K extends string>(prop: K): <T, U>(val: T, obj: U) => Record<K, T> & U;
I'm not sure, but I believe this is an oversight on the @types/ramda
project. You could enhance the type definition through declaration merging in this way:
interface Static {
prop<P extends keyof T, T>(p: P): (obj: Record<P, T>) => T;
assoc<K extends keyof T, T>(prop: K): <T, U>(val: T, obj: U) => Record<K, T> & U;
}
And then type your updateKey
method like this, without the need for separate blocks to handle different key types:
const updateKey = <K extends keyof IAsset>(key: K) => R.lens(R.prop<K, IAsset>(key), R.assoc<K, IAsset>(key));
本文标签:
版权声明:本文标题:javascript - Typescript: How to type Ramda R.prop(key) T' is not assignable to parameter of type '(s: {}) =& 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745615239a2159248.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论