Skip to content

updateIn throw Uncaught TypeError: keyPath.slice is not a function for ArrayLike that does not implement slice if the keyPath can not update #2062

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

Closed
jdeniau opened this issue Feb 26, 2025 · 0 comments · Fixed by #2065

Comments

@jdeniau
Copy link
Member

jdeniau commented Feb 26, 2025

Description

The updateIn function does call coerceKeyPath on the keyPath.

The coerceKeyPath does check if the keyPath is an "ArrayLike". If true, the value is kept.

In the updateIn, if the keyPath does not match the object, then we call this line, that does construct its error message with keyPath.slice(0, i), but .slice might not exist on a custom ArrayLike method.

Here is the implementation of isArrayLike: https://github.com/immutable-js/immutable-js/blob/main/src/utils/isArrayLike.ts

Reproductible example

Define the custom array

class CustomArrayLike<T> implements ArrayLike<T> {
  readonly length: number;
  readonly [n: number]: T;

  constructor(length: number) {
    this.length = length;
    for (let i = 0; i < length; i++) {
      this[i] = undefined as any;
    }
  }

  // Define other methods if needed, but do not include the `slice` method
  // For example, you can define a method to set values
  set(index: number, value: T): void {
    if (index >= 0 && index < this.length) {
      this[index] = value;
    } else {
      throw new RangeError('Index out of bounds');
    }
  }

  // Define a method to get values
  get(index: number): T {
    if (index >= 0 && index < this.length) {
      return this[index];
    } else {
      throw new RangeError('Index out of bounds');
    }
  }
}

Code that throws

// create an ArrayLike
const customArray = new CustomArrayLike<number>(2);
customArray.set(0, 10);
customArray.set(1, 20);

// code that works perfectly
Immutable.updateIn({ 10 :{ 20 : 'a' }}, customArray2, (v) => `${v.toUpperCase()}`)
// does output { 10 :{ 20 : 'A' }}


Immutable.updateIn({ 10 : 'a' }, customArray2, (v) => `${v.toUpperCase()}`)
// does throw Uncaught TypeError: keyPath.slice is not a function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant