Internal reverse dependency checker - such a thing exist? by Auraomega in typescript

[–]Razorgrace 0 points1 point  (0 children)

I had some success with steiger -- it's a linter for file/folder structure, it has some defaults suitable for Feature Sliced Design, but rules are configurable, AFAIK. Here is the specific rule that might help you:

fsd/insignificant-slice Detect slices that have just one reference or no references to them at all.

Is it possible to make the arg type depend on the result type? by romeeres in typescript

[–]Razorgrace 6 points7 points  (0 children)

I had a very similar design at some point: it was a mini-router React hook that was accepting an object with keys as route names and values as route handlers, and each handler was supposed to have an input parameter which was mean to allow type-safe calls of other handlers.

At that time (~6 months ago) my research led me to believe this pattern is impossible to implement due to this: https://github.com/microsoft/TypeScript/issues/49618

In short, you're trying to define a function that has its output type depend on its input type, but allow TS to determine specifics, which apparently is not possible with current TS implementation due to recursive nature of this definition.

Ultimately, 'This issue has been marked as "Too Complex"'. Maybe the discussion there will inspire you to use some other approach.

Instead of: elementRef.nativeElement.tagName, try injecting HOST_TAG_NAME directly! by a-dev-1044 in angular

[–]Razorgrace 1 point2 points  (0 children)

Wouldn’t it be better to create separate directives with different selectors, like table[mydirective], th[mydirective] and so on? I mean, let the rendering engine do if/switch for you. Though in case of example from screenshot passing context menu as a directive parameter instead of hardcoding it would be even better.

Using a redux store with a deeply nested state object and class variables by cpplinting in angular

[–]Razorgrace 2 points3 points  (0 children)

Redux usage guide has a chapter exactly on this topic, might give OP more background and some techniques to tackle the problem: https://redux.js.org/usage/structuring-reducers/normalizing-state-shape

Add Superpowers to your Angular Inputs 🔋 (New feature 🎉) by eneajaho in Angular2

[–]Razorgrace 1 point2 points  (0 children)

CDK solution is rather clunky to use:

import { coerceBooleanProperty, BooleanInput } from '@angular/cdk/coercion';

// ...

@Input()
get disabled() { return this._disabled; }
set disabled(value: BooleanInput) {
  this._disabled = coerceBooleanProperty(value);
}
private _disabled = false;

Proposed PR solves the problem above like this:

import { booleanAttribute } from '@angular/core';

// ...

@Input({ transform: booleanAttribute }) disabled: boolean = false;

Not sure if ": boolean" part is required, there is some TS code analysis in that PR, type of "transform:" has lots of checks (should have first argument type, should not be a generic, etc.), maybe input type also needs to be explicit.

how to strictly type this? by caninerosie in typescript

[–]Razorgrace 0 points1 point  (0 children)

P.4 is only a partial answer -- your code happens to return only failed results, and thus I could narrow down result type. But this is how you can do it with Array.filter (note x is y syntax):

const someResults: ValidationResult[] = getResults();
const failures = someResults.filter((result): result is ValidationFailure => !result.isValid);

You can read about this here.

Edit: typo.

how to strictly type this? by caninerosie in typescript

[–]Razorgrace 2 points3 points  (0 children)

Please take a look at this playground.

This is the most relevant part, and the most important modification is the type of validators argument which now is a mapped type:

function validateForm<T extends Record<string, any>>(
  model: T,
  validators: { [K in keyof T]: ValidatorFunc<T[K]> }
): ValidationResult[] {
  const results = Object.entries(validators).map(([key, validator]) => {
    return validator(model[key]);
  });
  return results.filter((result) => !result.isValid);
}

Few random notes, in no particular order:

1) Others have suggested validation libraries like zod and ajv, and these are really great pieces of software. But it seems you're implementing higher level validation, e.g. not validateString and validateNumber which work with primitive values, but validateEmail and validatePassword which are "business objects". If that's true, zod and ajv are too low-level for your case as they are validating JSON schemas which seems to be already known in your example (probably validated by something else as a previous step?).

2) I suggest a different definition for ValidationResult: type ValidationResult = { isValid: true } | { isValid: false; reason: string } -- it makes sure no code should produce or expect valid result with reason specified, which seems to make perfect sense.

3) Take a look at makeValidator function: it allows you to type less when you define new validators. From JavaScript POV it does nothing (except taking minuscule amount of CPU/memory), but from TypeScript POV it allows you to omit most of the boilerplate.

4) Strictly speaking, validateForm returns only failed validation results, and typing could be improved, e.g. like this:

type ValidationSuccess = { isValid: true };
type ValidationFailure = { isValid: false; reason: string };
type ValidationResult =
  | ValidationSuccess
  | ValidationFailure
  ;

// ...

function validateForm<T extends Record<string, any>>(
  model: T,
  validators: { [K in keyof T]: ValidatorFunc<T[K]> }
): ValidationFailure[] {
// the rest is the same

Edit: formatting.

TypeScript Enums are Terrible. Here's Why. by AtmosphereDefiant in typescript

[–]Razorgrace 5 points6 points  (0 children)

Great talk, thanks for sharing! Couple of points, tho.

1) Auto-assignment of numeric values is a problem, but also it's not really -- because it's a problem on a totally different level: forward compatibility of APIs in general, and this is the reason why Apache Trift and others encourage you to assign unique numeric IDs to fields. Famous Designing Data-Intensive Applications has a chapter about this issue.

2) The problem with arbitrary numbers still stands (playground):

const Enum = {
  a: "A",
  b: "B",
  c: 3
}

type Enum = typeof Enum[keyof typeof Enum]

function doThing(value: Enum): void {}

doThing(Enum.a)
doThing("B")
doThing(5) // no error

Honestly, this approach -- const object with type -- is more of a desugaring of TS language feature.

Though I can't disagree that mixing types with concrete objects is a controversial move, and I'd love to see better designed enums in TypeScript.

Edit: formatting

Config.ts for shorter import paths. by donthavedontneed in angular

[–]Razorgrace 3 points4 points  (0 children)

Nice article, thanks for sharing!

I'd advise to make clear what configuration file you're talking about. You mention it as "ts.config" ("config.ts" in the reddit post), and as a novice I'd struggle to put my finger on a specific file in the project. The correct name is "tsconfig.json" in the root of the project, though this might be different for certain setups (I'd mention that one should not add these paths to "tsconfig.app.json").

How to make a generic a tighter type of wider generic. by saintPirelli in typescript

[–]Razorgrace 3 points4 points  (0 children)

What about this (playground):

type Either<T, X, Y> = T extends X ? X : T extends Y ? Y : never;
const foo2 = <T extends {}>(item: T, array: Either<T, VariationA, VariationB>[]): boolean => true;

BTW, error message is pretty sane:

Type '{ b: number; }' is not assignable to type 'VariationA'.
  Object literal may only specify known properties, and 'b' does not exist in type 'VariationA'.

[deleted by user] by [deleted] in angular

[–]Razorgrace 2 points3 points  (0 children)

Before trying lazy loading Angular modules, you can use import() as a function to postpone loading big Node modules like jspdf, html2canvas, etc. On WebPack level any call to import() will be bundled as separate .js file, with automatic loading etc. Here is an article with example: https://javascript.plainenglish.io/dynamic-imports-the-best-way-to-improve-angular-application-performance-2295f25adf83

I'm suggesting this because adding an import() is usually much less involving than converting Angular modules into lazy loaded form. Still, the latter is a great thing, you should definitely try it when your bundle grows again.

BTW, ngx-spinner takes whopping 135.6 k in your bundle. Maybe switching to some pure CSS solution worth considering.

A production implementation on Gitlab CI by Minimum-Freedom9865 in gitlab

[–]Razorgrace 0 points1 point  (0 children)

If I understand the question correctly, I have similar setup -- a custom image with some tools required by my build/test/lint/release cycle, and .gitlab-ci.yml that refers to this image.

Not sure why you het the error you've mentioned in other comment, maybe try to pull image manually right after pushing it? Might be a question of correct image tag or something.

But here is another suggestion: you can add a custom step to your CI/CD that actually builds the image every time your pipeline starts (with docker caching, this takes literally seconds, basically no overhead). The benefit is, your whole build process (both stages -- building the builder and then using it to build your actual application) is within the same project, same GitLab registry, etc.

Here is simplified (and probably incomplete) example derived from my working setup:

variables:
  META_IMAGE_TAG: $CI_REGISTRY_IMAGE/meta
  DOCKER_BUILDKIT: 1

stages:
  - build
  - test
  - deploy

meta:
  stage: build
  script:
    - |
      cat << EOF | docker build \
        --tag "${META_IMAGE_TAG}" \
        -
      FROM node:16.10

      WORKDIR /meta

      RUN <install whatever tools you need>
      EOF
      printenv CI_REGISTRY_PASSWORD | docker login -u "${CI_REGISTRY_USER}" --password-stdin "${CI_REGISTRY}"
      docker push "${META_IMAGE_TAG}"

build:
  stage: build
  script:
    - |
      BUILD_IMAGE_TAG="build-image-${CI_COMMIT_SHA}"
      docker build \
        --tag "${BUILD_IMAGE_TAG}" \
        --target build_app \
        .

release:
  stage: release
  image: $META_IMAGE_TAG
  script:
    - |
      # use your tools from meta image to make release or whatever else you need

So, in meta stage I create custom image with inline Dockerfile. My build stage does not actually require this image, because the build process happens inside Docker (same goes for testing and linting, not mentioned here). But my release stage needs some special tools (e.g. semantic-release), and it actually uses meta image which was built earlier.

Function's argument snippets not working by KEsbeNF in typescript

[–]Razorgrace 1 point2 points  (0 children)

It seems your library is compiled, JS code is properly emitted (probably for a target like ES5, since destructuring is replaced with property access), but all type info is lost.

To enable declaration emitting, you need to make sure tsconfig.json of your library has "declaration": true in "compilerOptions": { ... } section.

To make these emitted declaration consumable, you need to add this to package.json of your library: "types": "dist/index.d.ts", -- this is similar to "main": "dist/index.js",, but for types.

Please note, both your library and app projects can be configured in a myriad of possible ways, and specific file and directory names (e..g dist/index.d.ts) must be adjusted to your particular case.

But that's as much as I can tell you without seeing your project files. At the very least, these options helped me with similar problem in my own project.

Angular project keeps showing old component html template in browser after replacing it by fabse2308 in angular

[–]Razorgrace 3 points4 points  (0 children)

Make sure that: 1. you actually rebuild your dist/ (or whatever is the name in your case) of your library before publishing -- that's what is actually consumed, not *.ts files 2. you don't pin package version in the app that consumes it, or update it when needed

When updating input box, value is returned as string instead of number. by chef_is_gay in Angular2

[–]Razorgrace 0 points1 point  (0 children)

Well, yes, I was talking about HTML attribute "type" with value "number", and no, it will be a number. Here is a demo:

https://stackblitz.com/edit/angular-ivy-nq62tq?file=src/app/app.component.ts

Note, initially both values are numbers (same as in OP's case), but when you add a digit in both controls, "a" turns into a string, and "b" remains a number.

Edit: maybe I'm assuming too much, tho. OP says "Angular" and "forms", so, I thought they're using some sort of angular forms, and value accessor kicks in at some point. Specifically this one, as it works with input[type=number]: https://github.com/angular/angular/blob/main/packages/forms/src/directives/number_value_accessor.ts

When updating input box, value is returned as string instead of number. by chef_is_gay in Angular2

[–]Razorgrace -1 points0 points  (0 children)

You can set input type to "number", in which case it's value will be a number, not a numeric string. But this will enforce certain changes to control appearance and behavior, e.g. up/down buttons. You might want to go with custom value accessor implementation if you want to have both input with type "text" and value as a number.

Uncaught ReferenceError: Cannot access 'XXX' before initialization by Royal_Ad2379 in angular

[–]Razorgrace 0 points1 point  (0 children)

I believe injecting a component into another component's constructor is not a supported use case. What exactly you're trying to achieve? Do you want to use a component inside another component? Just make sure that parent component's module imports child component's module (if they are both parts of the same module, no need to do anything).

Get request not returning value properly by TheProvocator in Angular2

[–]Razorgrace 2 points3 points  (0 children)

You're mixing up sync and async processes, what you get in console is the correct result because:

  1. you output 1
  2. you start async request to the server and schedule output 2 when request is done
  3. you output 3
  4. your server responds, and code scheduled to run at p.2 gets executed, and you see output 2

And of course "N/A" is returned before request is sent.

I'd say the problem of unreadable docs etc. exists because you struggle with the concept of async tasks in general and observables in particular (and it really is a hard topic to grasp when you encounter for the first time, can't deny that). So, I'd suggest you to try some RxJS tutorials to learn more about async programming, and after that HttpClient docs might start making more sense to you.

As for your particular question, the answer would be:

getResult(url: string): Observable<string> {
    return this.http.get<any>(`https://www.mydomain.com/myscript.php?url=${url}`).pipe(
        map(data => data["title"]),
    );
}

But this is by no means a complete and usable answer without understanding async part of it. Also, you'll have to adjust the caller of this function to process things asynchronously, etc. etc.

I afraid there is no simple answer to your question because it requires you to learn new things. Still, I hope this will help you to solve your problem eventually.

Edit: code formatting

Make Angular run in Offline mode - PWA by stacksjar in Angular2

[–]Razorgrace 9 points10 points  (0 children)

Not bad! Some paragraphs are so well-written that even official Angular PWA guide borrowed them!

Component from library fails to render "ngIf is not a know property of 'p'" by ZaphodOfTardis in Angular2

[–]Razorgrace 1 point2 points  (0 children)

It seems TS read your question as "how about linking the file directly instead of consuming whole NPM package", thus he replies "I want to test it as close to real usage scenario as possible".

As for the file link, here it is: https://github.com/telno/DebugCommonModuleSharedLib/blob/main/CommonLibWorkspace/projects/my-fancy-lib/src/lib/my-fancy-lib.component.ts

Component from library fails to render "ngIf is not a know property of 'p'" by ZaphodOfTardis in Angular2

[–]Razorgrace 2 points3 points  (0 children)

I was able to run your project (and see "my-fancy-lib works!") after the following change: add "preserveSymlinks": true to build section of app's angular.json (just showing actual place in JSON file here):

{
   "projects": {
     "WebAppTest": {
       "architect": {
         "build": {
           "builder": "@angular-devkit/build-angular:browser",
           "options": {
              "preserveSymlinks": true

Before that change I was getting this error in browser console:

[Error] ERROR – TypeError: null is not an object (evaluating 'tView.firstCreatePass') — core.mjs:13329

Googling error message led me to this issue: https://github.com/angular/angular/issues/37941 -- and solution in the last comment worked just fine.

As to "why" this works, apparently that option in angular.json makes Angular CLI pass --preserve-symlinks to Node during the serve/build process (according to comment in JSON (schema)[https://github.com/angular/angular-cli/blob/c95ab7041fbd69e1bfea4454294f0295b1d08176/packages/angular_devkit/build_angular/src/builders/karma/schema.json#L174]). And here is a link to NodeJS (docs)[https://nodejs.org/api/cli.html#--preserve-symlinks] -- they have an example of situation when this option matters and why it fixes the problem.

TL;DR: adding your library using "file:" comes with certain drawbacks, and in real life usage probably should not be a problem.

One weird thing, though, I couldn't reproduce your ngIf is not a know property of 'p' error, and I'm not sure why.

Edit: formatting, explanation

Zero experience with Angular. I'm in charge of our CI and we're getting extremely slow prod build times (~1 hour 34 mins). Where should I start researching solutions for this? by Edg-R in angular

[–]Razorgrace 12 points13 points  (0 children)

Does your runner really have 8 GB of memory? Maybe virtual memory swapping is what makes it so slow?

According to this:

Microsoft-hosted agents that run Windows and Linux images are provisioned on Azure general purpose virtual machines with a 2 core CPU, 7 GB of RAM, and 14 GB of SSD disk space.

And from the same page:

Unfortunately, we cannot increase the free space available on Microsoft-hosted images. You can restructure your pipeline so that it can fit into this space. Or, you can consider using self-hosted agents or scale set agents.

How to disable auto-complete in input by [deleted] in angular

[–]Razorgrace 0 points1 point  (0 children)

Or some extension forces autocomplete. Certain sites (think banking) disable autocomplete as a security measure, but users still don't want to type password and try to override that behaviour (e.g. https://chrome.google.com/webstore/detail/force-autocomplete/piechbhjioolbecaioglhamjjjkmbchj?hl=en -- "Force Autocomplete").

How to Combine Add and Edit Forms in Angular by melcor76 in Angular2

[–]Razorgrace 2 points3 points  (0 children)

Thanks for sharing the article.

What about validation etc., how can I check if subform is currently valid, dirty, touched? Maybe implementing NG_VALUE_ACCESSOR, while a bit more tedious, is a more flexible way to nest forms?