You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中完全禁止接口继承时的属性重写

How to Disallow Overriding Interface Properties During Inheritance in TypeScript

If you want to block any property override when extending an interface—regardless of whether the new type is compatible with the parent's—here are two reliable solutions tailored to your React component props scenario:

Since neither TypeScript nor default ESLint rules enforce this behavior out of the box, a custom rule will catch accidental overrides as you code. Here's how to build it:

Step 1: Install Dependencies

First, add the required TypeScript ESLint utilities:

npm install --save-dev @typescript-eslint/utils @typescript-eslint/eslint-plugin

Step 2: Create the Custom Rule

Make a new file (e.g., eslint-rules/no-interface-property-override.js) with this code:

const { ESLintUtils } = require('@typescript-eslint/utils');

const createRule = ESLintUtils.RuleCreator(
  () => 'https://your-project-docs.com/rules/no-interface-property-override' // Placeholder URL for your project docs
);

module.exports = createRule({
  create(context) {
    const parserServices = ESLintUtils.getParserServices(context);
    const typeChecker = parserServices.program.getTypeChecker();

    return {
      InterfaceDeclaration(node) {
        // Skip interfaces without parent extensions
        if (!node.extends || node.extends.length === 0) return;

        // Extract property names from the current interface
        const currentProps = node.body.body
          .filter(item => item.type === 'TSPropertySignature')
          .map(item => item.key.name);

        // Check each inherited parent interface
        for (const heritageClause of node.extends) {
          for (const typeNode of heritageClause.types) {
            const parentType = typeChecker.getTypeAtLocation(typeNode);
            const parentProps = typeChecker.getPropertiesOfType(parentType)
              .map(prop => prop.name);

            // Find overlapping properties and report errors
            const overlapping = currentProps.filter(prop => parentProps.includes(prop));
            overlapping.forEach(prop => {
              context.report({
                node: node.body.body.find(item => item.key.name === prop),
                messageId: 'forbiddenOverride',
                data: { prop },
              });
            });
          }
        }
      },
    };
  },
  name: 'no-interface-property-override',
  meta: {
    type: 'problem',
    docs: {
      description: 'Prevent overriding properties when extending an interface',
      recommended: 'error',
    },
    messages: {
      forbiddenOverride: 'Property "{{prop}}" is already defined in the parent interface. Avoid overriding inherited properties.',
    },
    schema: [],
  },
  defaultOptions: [],
});

Step 3: Configure ESLint

Update your .eslintrc.js to enable the custom rule:

module.exports = {
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  rules: {
    './eslint-rules/no-interface-property-override': 'error', // Use 'warn' if you prefer warnings over errors
  },
};

Now, any time you define a property in your component props interface that already exists in the inherited HTML props (like color in ButtonProps), ESLint will throw an error immediately.

2. TypeScript Type Guard (Manual Safety Net)

If you prefer a TypeScript-only solution (without ESLint), you can create a type utility that enforces no overlapping properties:

// Type utility to ensure T has no properties overlapping with U
type NoInheritedOverrides<T, U> = Exclude<keyof T, keyof U> extends never ? T : never;

// Example usage with your React component props
type HTMLButtonProps = JSX.IntrinsicElements["button"];

interface ButtonProps extends HTMLButtonProps {
  // This will trigger a TypeScript error because 'color' exists in HTMLButtonProps
  color: "primary" | "secondary";
}

// Enforce the check: if ButtonProps has overrides, this will be 'never' and throw an error
type CheckedButtonProps = NoInheritedOverrides<ButtonProps, HTMLButtonProps>;

This will cause a TypeScript error if your ButtonProps includes any property from HTMLButtonProps, but you'll need to add the CheckedButtonProps type explicitly for each component.

Key Notes

  • The ESLint rule is better for long-term use because it works automatically across your entire codebase.
  • Both solutions work perfectly for React scenarios where you want to avoid accidentally overriding native HTML element props.

内容的提问来源于stack exchange,提问作者Darkbound

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 19:52:46