dsherret / ts-nameof

nameof in TypeScript
MIT License
492 stars 23 forks source link

No compile errors #111

Closed sebascomeau closed 3 years ago

sebascomeau commented 3 years ago

I using ts-nameof to reduce the number of petiential bug that string can cause when using class or interface prop names. It work great in general but if I type the wrong prop name then it compile without any errors. Am I doing someting wrong or it's something that you can't manage?

I tried both babel typescript and babel macros ways to compile and both do the same behavior, no error caught. I'm working on a new NextJs project.

node version: 14.16.0

tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve"
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

packages.json

{
  "$schema": "https://json.schemastore.org/package",
  "name": "my-project",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_OPTIONS='--inspect' next dev",
    "build": "next build",
    "start": "next start",
  },
  "dependencies": {
    "@microsoft/applicationinsights-web": "^2.5.11",
    "@types/ts-nameof": "^4.2.1",
    "babel-plugin-ts-nameof": "^4.2.1",
    "google-libphonenumber": "^3.2.18",
    "lodash": "^4.17.21",
    "next": "^10.0.8",
    "next-seo": "^4.20.0",
    "next-translate": "^1.0.4",
    "react": "^17.0.1",
    "react-bootstrap": "0.33.1",
    "react-dom": "^17.0.1",
    "react-query": "^3.12.1",
    "yup": "^0.32.9"
  },
  "devDependencies": {
    "@babel/cli": "^7.13.10",
    "@babel/preset-env": "^7.13.10",
    "@types/google-libphonenumber": "^7.4.19",
    "@types/lodash": "^4.14.168",
    "@types/node": "^14.14.34",
    "@types/preval.macro": "^3.0.0",
    "@types/react": "^17.0.3",
    "@types/react-bootstrap": "^0.32.25",
    "@types/react-query": "^1.1.2",
    "@typescript-eslint/eslint-plugin": "^4.17.0",
    "@typescript-eslint/parser": "^4.17.0",
    "autoprefixer": "^10.2.5",
    "babel-plugin-lodash": "^3.3.4",
    "babel-plugin-macros": "^3.0.1",
    "cross-env": "^7.0.3",
    "eslint": "^7.22.0",
    "eslint-config-prettier": "^8.1.0",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-react": "^7.22.0",
    "eslint-plugin-react-hooks": "^4.2.0",
    "postcss": "^8.2.8",
    "prettier": "^2.2.1",
    "preval.macro": "^5.0.0",
    "tailwindcss": "^2.0.3",
    "typescript": "^4.2.3"
  },
  "babel": {
    "presets": [
      "next/babel"
    ],
    "plugins": [
      "babel-plugin-macros",
      "babel-plugin-ts-nameof",
      "lodash"
    ]
  },
  "eslintConfig": {
    "env": {
      "browser": true,
      "es6": true,
      "node": true
    },
    "extends": [
      "eslint:recommended",
      "plugin:@typescript-eslint/recommended",
      "plugin:react/recommended",
      "plugin:react-hooks/recommended",
      "plugin:jsx-a11y/recommended",
      "plugin:prettier/recommended"
    ],
    "overrides": [
      {
        "files": [
          "**/*.ts",
          "**/*.tsx"
        ]
      }
    ],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
      "ecmaVersion": 2020
    },
    "rules": {
      "react/prop-types": "off",
      "react/react-in-jsx-scope": "off",
      "jsx-a11y/anchor-is-valid": "off",
      "@typescript-eslint/no-unused-vars": [
        "error",
        {
          "argsIgnorePattern": "^_"
        }
      ],
      "@typescript-eslint/explicit-function-return-type": [
        "warn",
        {
          "allowExpressions": true,
          "allowConciseArrowFunctionExpressionsStartingWithVoid": true
        }
      ]
    },
    "settings": {
      "react": {
        "version": "detect"
      }
    }
  },
  "prettier": {
    "arrowParens": "always",
    "endOfLine": "lf",
    "jsxBracketSameLine": true,
    "printWidth": 256,
    "singleQuote": true,
    "tabWidth": 2
  }
}
dsherret commented 3 years ago

@sebascomeau if you use the wrong property name elsewhere, does it cause a compile error? I'm wondering if type checking happens at all. Type checking should happen before the ts-nameof transformation so you should get a compile error.

sebascomeau commented 3 years ago

Type checking doesn't seems to work at all. I just move some fields from interfaces and no errors.

dsherret commented 3 years ago

@sebascomeau is this option set to true? https://nextjs.org/docs/api-reference/next.config.js/ignoring-typescript-errors

sebascomeau commented 3 years ago

This option is not set to default to false.

I get error if I put the wrong type name in nameof(o => o.{prop}). image

But if I type the wrong prop name then no error and it build. image

But I get an error if the prop name is type Interface. Good image Error image

With wrong name of that prop no error... image

Prop Correct image

Prop name NOT Correct with no error image

I think I just found the problem.... image

Index Types... it's the reason why I dont get any error.

dsherret commented 3 years ago

@sebascomeau yes, that looks like the problem.

sebascomeau commented 3 years ago

I need Index Types because I have a generic funtion to updated string type with field name.

const handleOnTextFieldChange: TextFieldOnChangeEvent & TextAreaFieldOnChangeEvent = ({ field, value }) => {
    setFormDataState((prev) => {
      const newObj = { ...prev.expressionOfInterest, [field]: value ?? undefined };
      return { ...prev, expressionOfInterest: newObj };
    });
  };
sebascomeau commented 3 years ago

You should add a note on that in the documentation.

dsherret commented 3 years ago

@sebascomeau you may want to create a separate type that doesn't have the index type.

interface TypeWithOnlyProperties {
    prop: string;
}

interface TypeWithEverything extends TypeWithOnlyProperties {
    [key: string]: string | undefined;
}

nameof<TypeWithOnlyProperties>(o => o.otherProp); // error
sebascomeau commented 3 years ago

Thanks for the tips. I will do that.