5

I need the ability to easily sort collections and I've chosen to extend the Array primitive. I realize this is considered bad practice in most cases, but this will be used only internally (not a shared lib). No matter what approach I've tried I'm not getting a working result. I keep getting the error: TypeError: Attempted to assign to readonly property. This is a simplified example of my latest iteration. I have a more complete version of this working in the playground so I'm assuming he problem lies with the angular-cli config/build process???

interface Array<T> {
  $sortBy(sortKey:string): T[];
}

if (!Array.prototype['$sortBy']) {

  Object.defineProperty(Array.prototype, '$sortBy', {
    value: function(sortKey) {
      return this.sort( function(a, b) { // TypeError here???
        if (a[sortKey] < b[sortKey]) { return -1; }
        if (a[sortKey] > b[sortKey]) { return 1; }
        return 0;
      });
    }
  }

}

I've also tried this approach but my IDE (VSCode) gives me the error: [ts] Property '$sortBy' does not exist on type 'any[]'.

         Intellisense error here
                   |
                   V
Array.prototype.$sortBy = function(sortKey:string){
  return this.sort( function(a, b) {
    ...
  });
}

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "lib": [
      "es2016"
    ]
  }
}

tsconfig.app.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
  "lib": [
    "es2016",
    "dom"
  ],
    "outDir": "../out-tsc/app",
    "target": "es5",
    "module": "es2015",
    "baseUrl": "",
    "types": []
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]
}
9
  • Which version of typescript are you using? What's your tsconfig.json? Your code works fine in playground. Commented Mar 21, 2017 at 21:27
  • Maybe github.com/basarat/typescript-collections has something that would suit your needs better. I haven't tried the array utilities but the data structures are nice. Commented Mar 21, 2017 at 21:35
  • Checkout: stackoverflow.com/questions/14000645/… Starting in TypeScript 1.6, you can extend the Array type Commented Mar 21, 2017 at 21:36
  • @NitzanTomer added my ts configs above. I'm using TS 2.1.6. This is an angular-cli project Commented Mar 21, 2017 at 21:37
  • 1
    Also, regardless of your problem, extending of the Array<T> interface needs to be outside of the if (!Array.prototype['$sortBy']) Commented Mar 21, 2017 at 21:48

1 Answer 1

1

I had this problem as well, so just pasting my results here in case someone needs.

in your main.ts file add this:

// Here will be all extension methods that will be shared globally across the app
declare global {
  interface Array<T> {
    sortAlphaNumeric(fieldName: string): Array<T>;
  }
}

then you can create a file with this:

    /** 
     * The extension of Array type allows to sort AlphaNumeric data
     * @param fieldName {string} requires the field name which you want to sort by
     */
    Array.prototype.sortAlphaNumeric = function (fieldName: string) {
        return this.sort((a, b) => {
            return a[fieldName].toLowerCase().localeCompare(b[fieldName].toLowerCase(), undefined, {
                numeric: true,
                sensitivity: 'base'
            });
        });
    };
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.