diff --git a/README.md b/README.md
index 3315bd3ba..db731dd26 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ npm install --save-dev svelte eslint eslint-plugin-svelte globals
 > **Requirements:**
 >
 > - ESLint v8.57.1, v9.0.0, and above
-> - Node.js v18.20.4, v20.18.0, v22.10.0, and above
+> - Node.js v18.18.0, v20.9.0, v21.1.0 and above
 
 ## Usage
 
diff --git a/docs/rules/no-unused-props.md b/docs/rules/no-unused-props.md
index c375aa430..fffe3864f 100644
--- a/docs/rules/no-unused-props.md
+++ b/docs/rules/no-unused-props.md
@@ -159,14 +159,17 @@ Note: Properties of class types are not checked for usage, as they might be used
   "svelte/no-unused-props": ["error", {
     // Whether to check properties from imported types
     "checkImportedTypes": false,
+    // Patterns to ignore when checking property types
+    "ignoreTypePatterns": [],
     // Patterns to ignore when checking for unused props
-    "ignorePatterns": []
+    "ignorePropertyPatterns": [],
   }]
 }
 ```
 
-- `checkImportedTypes` ... Controls whether to check properties from imported types. Default is `false`.
-- `ignorePatterns` ... Patterns to ignore when checking for unused props. Default is an empty array.
+- `checkImportedTypes` ... Controls whether to check properties from types defined in external files. Default is `false`, meaning the rule only checks types defined within the component file itself. When set to `true`, the rule will also check properties from imported and extended types.
+- `ignoreTypePatterns` ... Regular expression patterns for type names to exclude from checks. Default is `[]` (no exclusions). Most useful when `checkImportedTypes` is `true`, allowing you to exclude specific imported types (like utility types or third-party types) from being checked.
+- `ignorePropertyPatterns` ... Regular expression patterns for property names to exclude from unused checks. Default is `[]` (no exclusions). Most useful when `checkImportedTypes` is `true`, allowing you to ignore specific properties from external types that shouldn't trigger warnings.
 
 Examples:
 
@@ -187,8 +190,26 @@ Examples:
 ```svelte
 <!-- ✓ Good Examples -->
 <script lang="ts">
-  /* eslint svelte/no-unused-props: ["error", { "ignorePatterns": ["^_"] }] */
-  // Ignore properties starting with underscore
+  /* eslint svelte/no-unused-props: ["error", { "ignoreTypePatterns": ["/^Internal/"] }] */
+  // Ignore properties from types matching the pattern
+  interface InternalConfig {
+    secretKey: string;
+    debugMode: boolean;
+  }
+  interface Props {
+    config: InternalConfig;
+    value: number;
+  }
+  let { config, value }: Props = $props();
+  console.log(value, config.secretKey);
+</script>
+```
+
+```svelte
+<!-- ✓ Good Examples -->
+<script lang="ts">
+  /* eslint svelte/no-unused-props: ["error", { "ignorePropertyPatterns": ["/^_/"] }] */
+  // Ignore properties with names matching the pattern
   interface Props {
     _internal: string;
     value: number;
diff --git a/docs/user-guide.md b/docs/user-guide.md
index 0eba2e2bd..babec87fa 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -13,7 +13,7 @@ npm install --save-dev svelte eslint eslint-plugin-svelte globals
 > **Requirements:**
 >
 > - ESLint v8.57.1, v9.0.0, and above
-> - Node.js v18.20.4, v20.18.0, v22.10.0, and above
+> - Node.js v18.18.0, v20.9.0, v21.1.0 and above
 
 ## Usage
 
diff --git a/package.json b/package.json
index 4c02f05d2..254352fc5 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,7 @@
     "@typescript-eslint/parser": "^8.16.0",
     "c8": "^10.1.2",
     "env-cmd": "^10.1.0",
-    "eslint": "~9.22.0",
+    "eslint": "~9.23.0",
     "eslint-config-prettier": "^10.0.0",
     "eslint-formatter-friendly": "^7.0.0",
     "eslint-plugin-eslint-plugin": "^6.3.2",
diff --git a/packages/eslint-plugin-svelte/CHANGELOG.md b/packages/eslint-plugin-svelte/CHANGELOG.md
index 9aa040e0a..23a4fba9e 100644
--- a/packages/eslint-plugin-svelte/CHANGELOG.md
+++ b/packages/eslint-plugin-svelte/CHANGELOG.md
@@ -1,5 +1,41 @@
 # eslint-plugin-svelte
 
+## 3.3.3
+
+### Patch Changes
+
+- [#1146](https://github.com/sveltejs/eslint-plugin-svelte/pull/1146) [`1233e46`](https://github.com/sveltejs/eslint-plugin-svelte/commit/1233e46413132c1e81dc69981be1533c5e6c6a4d) Thanks [@baseballyama](https://github.com/baseballyama)! - fix(no-unused-props): resolve false positives on props with default values or $bindable usage
+
+## 3.3.2
+
+### Patch Changes
+
+- [#1143](https://github.com/sveltejs/eslint-plugin-svelte/pull/1143) [`138380d`](https://github.com/sveltejs/eslint-plugin-svelte/commit/138380deeec2ccd0189b70abf7d9a2cd6b608338) Thanks [@baseballyama](https://github.com/baseballyama)! - fix: stop reporting child properties in `no-unused-props` when the parent object itself is used
+
+## 3.3.1
+
+### Patch Changes
+
+- [#1140](https://github.com/sveltejs/eslint-plugin-svelte/pull/1140) [`40806a4`](https://github.com/sveltejs/eslint-plugin-svelte/commit/40806a4b6342a7f2d1bd40d65df8dec5af666e1a) Thanks [@ota-meshi](https://github.com/ota-meshi)! - fix(no-useless-mustaches): Wrong auto-fix for quoted mustaches
+
+## 3.3.0
+
+### Minor Changes
+
+- [#1132](https://github.com/sveltejs/eslint-plugin-svelte/pull/1132) [`30c1e5f`](https://github.com/sveltejs/eslint-plugin-svelte/commit/30c1e5fc6517cec7171ca42327699c3ad9ab6580) Thanks [@baseballyama](https://github.com/baseballyama)! - feat: add `ignorePropertyPatterns` property and rename `ignorePatterns` to `ignoreTypePatterns` in `no-unused-props` rule. The `ignorePatterns` option existed only for a few hours and is removed by this PR. Technically, this is a breaking change, but we’ll handle it as a minor release since very few users are likely affected.
+
+## 3.2.2
+
+### Patch Changes
+
+- [#1135](https://github.com/sveltejs/eslint-plugin-svelte/pull/1135) [`1ff148a`](https://github.com/sveltejs/eslint-plugin-svelte/commit/1ff148a0bb24954aef59ce93b05a35913d83f2ee) Thanks [@baseballyama](https://github.com/baseballyama)! - fix: correct detection of externally defined types in `no-unused-props` rule
+
+## 3.2.1
+
+### Patch Changes
+
+- [#1128](https://github.com/sveltejs/eslint-plugin-svelte/pull/1128) [`e94b59a`](https://github.com/sveltejs/eslint-plugin-svelte/commit/e94b59a35c914d868f89dd300b8d6b8090054976) Thanks [@baseballyama](https://github.com/baseballyama)! - fix: resolve false positives on nested objects in `no-unused-props` rule
+
 ## 3.2.0
 
 ### Minor Changes
diff --git a/packages/eslint-plugin-svelte/package.json b/packages/eslint-plugin-svelte/package.json
index 06a83ab12..236ec8e09 100644
--- a/packages/eslint-plugin-svelte/package.json
+++ b/packages/eslint-plugin-svelte/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-svelte",
-  "version": "3.2.0",
+  "version": "3.3.3",
   "description": "ESLint plugin for Svelte using AST",
   "repository": "git+https://github.com/sveltejs/eslint-plugin-svelte.git",
   "homepage": "https://sveltejs.github.io/eslint-plugin-svelte",
diff --git a/packages/eslint-plugin-svelte/src/meta.ts b/packages/eslint-plugin-svelte/src/meta.ts
index 9de65a2c7..f3f181d74 100644
--- a/packages/eslint-plugin-svelte/src/meta.ts
+++ b/packages/eslint-plugin-svelte/src/meta.ts
@@ -2,4 +2,4 @@
 // This file has been automatically generated,
 // in order to update its content execute "pnpm run update"
 export const name = 'eslint-plugin-svelte';
-export const version = '3.2.0';
+export const version = '3.3.3';
diff --git a/packages/eslint-plugin-svelte/src/rule-types.ts b/packages/eslint-plugin-svelte/src/rule-types.ts
index 86e6d65b8..19e30a345 100644
--- a/packages/eslint-plugin-svelte/src/rule-types.ts
+++ b/packages/eslint-plugin-svelte/src/rule-types.ts
@@ -535,7 +535,8 @@ type SvelteNoUnusedClassName = []|[{
 // ----- svelte/no-unused-props -----
 type SvelteNoUnusedProps = []|[{
   checkImportedTypes?: boolean
-  ignorePatterns?: string[]
+  ignoreTypePatterns?: string[]
+  ignorePropertyPatterns?: string[]
 }]
 // ----- svelte/no-useless-mustaches -----
 type SvelteNoUselessMustaches = []|[{
diff --git a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts
index 1588f3b32..2ea58fd87 100644
--- a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts
+++ b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts
@@ -8,6 +8,8 @@ import { getFilename } from '../utils/compat.js';
 
 type PropertyPath = string[];
 
+let isRemovedWarningShown = false;
+
 export default createRule('no-unused-props', {
 	meta: {
 		docs: {
@@ -23,7 +25,14 @@ export default createRule('no-unused-props', {
 						type: 'boolean',
 						default: false
 					},
-					ignorePatterns: {
+					ignoreTypePatterns: {
+						type: 'array',
+						items: {
+							type: 'string'
+						},
+						default: []
+					},
+					ignorePropertyPatterns: {
 						type: 'array',
 						items: {
 							type: 'string'
@@ -61,34 +70,55 @@ export default createRule('no-unused-props', {
 		}
 
 		const options = context.options[0] ?? {};
+
+		// TODO: Remove in v4
+		// MEMO: `ignorePatterns` was a property that only existed from v3.2.0 to v3.2.2.
+		// From v3.3.0, it was replaced with `ignorePropertyPatterns` and `ignoreTypePatterns`.
+		if (options.ignorePatterns != null && !isRemovedWarningShown) {
+			console.warn(
+				'eslint-plugin-svelte: The `ignorePatterns` option in the `no-unused-props` rule has been removed. Please use `ignorePropertyPatterns` or/and `ignoreTypePatterns` instead.'
+			);
+			isRemovedWarningShown = true;
+		}
+
 		const checkImportedTypes = options.checkImportedTypes ?? false;
-		const ignorePatterns = (options.ignorePatterns ?? []).map((p: string | RegExp) => {
+
+		const ignoreTypePatterns = (options.ignoreTypePatterns ?? []).map((p: string | RegExp) => {
 			if (typeof p === 'string') {
 				return toRegExp(p);
 			}
 			return p;
 		});
 
-		function shouldIgnore(name: string): boolean {
-			return ignorePatterns.some((pattern: RegExp) => pattern.test(name));
+		const ignorePropertyPatterns = (options.ignorePropertyPatterns ?? []).map(
+			(p: string | RegExp) => {
+				if (typeof p === 'string') {
+					return toRegExp(p);
+				}
+				return p;
+			}
+		);
+
+		function shouldIgnoreProperty(name: string): boolean {
+			return ignorePropertyPatterns.some((pattern: RegExp) => pattern.test(name));
 		}
 
 		function shouldIgnoreType(type: ts.Type): boolean {
+			function isMatched(name: string): boolean {
+				return ignoreTypePatterns.some((pattern: RegExp) => pattern.test(name));
+			}
+
 			const typeStr = typeChecker.typeToString(type);
 			const symbol = type.getSymbol();
 			const symbolName = symbol?.getName();
-			return shouldIgnore(typeStr) || (symbolName ? shouldIgnore(symbolName) : false);
+			return isMatched(typeStr) || (symbolName ? isMatched(symbolName) : false);
 		}
 
-		function isExternalType(type: ts.Type): boolean {
-			const symbol = type.getSymbol();
-			if (!symbol) return false;
-
+		function isInternalProperty(symbol: ts.Symbol): boolean {
 			const declarations = symbol.getDeclarations();
 			if (!declarations || declarations.length === 0) return false;
 
-			const sourceFile = declarations[0].getSourceFile();
-			return sourceFile.fileName !== fileName;
+			return declarations.every((decl) => decl.getSourceFile().fileName === fileName);
 		}
 
 		/**
@@ -126,7 +156,12 @@ export default createRule('no-unused-props', {
 
 			const paths: PropertyPath[] = [];
 			for (const reference of variable.references) {
-				if ('identifier' in reference && reference.identifier.type === 'Identifier') {
+				if (
+					'identifier' in reference &&
+					reference.identifier.type === 'Identifier' &&
+					(reference.identifier.range[0] !== node.range[0] ||
+						reference.identifier.range[1] !== node.range[1])
+				) {
 					const referencePath = getPropertyPath(reference.identifier);
 					paths.push(referencePath);
 				}
@@ -200,7 +235,6 @@ export default createRule('no-unused-props', {
 			if (checkedTypes.has(typeStr)) return;
 			checkedTypes.add(typeStr);
 			if (shouldIgnoreType(type)) return;
-			if (!checkImportedTypes && isExternalType(type)) return;
 
 			const properties = typeChecker.getPropertiesOfType(type);
 			const baseTypes = type.getBaseTypes();
@@ -225,19 +259,28 @@ export default createRule('no-unused-props', {
 
 			for (const prop of properties) {
 				if (isBuiltInProperty(prop)) continue;
+				if (!checkImportedTypes && !isInternalProperty(prop)) continue;
 
 				const propName = prop.getName();
+				if (shouldIgnoreProperty(propName)) continue;
+
 				const currentPath = [...parentPath, propName];
 				const currentPathStr = [...parentPath, propName].join('.');
 
 				if (reportedProps.has(currentPathStr)) continue;
 
 				const propType = typeChecker.getTypeOfSymbol(prop);
-				const isUsedInPath = usedPaths.some((path) => {
-					const usedPath = path.join('.');
-					return usedPath === currentPathStr || usedPath.startsWith(`${currentPathStr}.`);
+
+				const joinedUsedPaths = usedPaths.map((path) => path.join('.'));
+				const isUsedThisInPath = joinedUsedPaths.includes(currentPathStr);
+				const isUsedInPath = joinedUsedPaths.some((path) => {
+					return path.startsWith(`${currentPathStr}.`);
 				});
 
+				if (isUsedThisInPath && !isUsedInPath) {
+					continue;
+				}
+
 				const isUsedInProps = usedProps.has(propName);
 
 				if (!isUsedInPath && !isUsedInProps) {
@@ -250,10 +293,11 @@ export default createRule('no-unused-props', {
 							parent: parentPath.join('.')
 						}
 					});
+					continue;
 				}
 
-				const isUsedNested = usedPaths.some((path) => {
-					return path.join('.').startsWith(`${currentPathStr}.`);
+				const isUsedNested = joinedUsedPaths.some((path) => {
+					return path.startsWith(`${currentPathStr}.`);
 				});
 
 				if (isUsedNested || isUsedInProps) {
@@ -292,6 +336,18 @@ export default createRule('no-unused-props', {
 			return usedProps.size === 0;
 		}
 
+		function normalizeUsedPaths(paths: PropertyPath[]): PropertyPath[] {
+			const normalized: PropertyPath[] = [];
+			for (const path of paths.sort((a, b) => a.length - b.length)) {
+				if (path.length === 0) continue;
+				if (normalized.some((p) => p.every((part, idx) => part === path[idx]))) {
+					continue;
+				}
+				normalized.push(path);
+			}
+			return normalized;
+		}
+
 		return {
 			'VariableDeclaration > VariableDeclarator': (node: TSESTree.VariableDeclarator) => {
 				// Only check $props declarations
@@ -313,13 +369,20 @@ export default createRule('no-unused-props', {
 				if (node.id.type === 'ObjectPattern') {
 					usedProps = getUsedPropertiesFromPattern(node.id);
 					if (usedProps.size === 0) return;
-					const identifiers = node.id.properties
-						.filter((p): p is TSESTree.Property => p.type === 'Property')
-						.map((p) => p.value)
-						.filter((v): v is TSESTree.Identifier => v.type === 'Identifier');
+					const identifiers: TSESTree.Identifier[] = [];
+					for (const p of node.id.properties) {
+						if (p.type !== 'Property') {
+							continue;
+						}
+						if (p.value.type === 'Identifier') {
+							identifiers.push(p.value);
+						} else if (p.value.type === 'AssignmentPattern' && p.value.left.type === 'Identifier') {
+							identifiers.push(p.value.left);
+						}
+					}
 					for (const identifier of identifiers) {
 						const paths = getUsedNestedPropertyNames(identifier);
-						usedPaths.push(...paths);
+						usedPaths.push(...paths.map((path) => [identifier.name, ...path]));
 					}
 				} else if (node.id.type === 'Identifier') {
 					usedPaths = getUsedNestedPropertyNames(node.id);
@@ -327,7 +390,7 @@ export default createRule('no-unused-props', {
 
 				checkUnusedProperties(
 					propType,
-					usedPaths,
+					normalizeUsedPaths(usedPaths),
 					usedProps,
 					node.id,
 					[],
diff --git a/packages/eslint-plugin-svelte/src/rules/no-useless-mustaches.ts b/packages/eslint-plugin-svelte/src/rules/no-useless-mustaches.ts
index 05d3af28e..d8da0cc11 100644
--- a/packages/eslint-plugin-svelte/src/rules/no-useless-mustaches.ts
+++ b/packages/eslint-plugin-svelte/src/rules/no-useless-mustaches.ts
@@ -142,14 +142,21 @@ export default createRule('no-useless-mustaches', {
 							node.parent.key.range[1],
 							node.parent.value[0].range[0]
 						);
-						if (!div.endsWith('"') && !div.endsWith("'")) {
+						const quote = div.endsWith('"') ? 'quot' : div.endsWith("'") ? 'apos' : null;
+						if (!quote) {
 							return [
 								fixer.insertTextBefore(node.parent.value[0], '"'),
 								fixer.replaceText(node, unescaped.replace(/"/gu, '&quot;')),
 								fixer.insertTextAfter(node.parent.value[node.parent.value.length - 1], '"')
 							];
 						}
-						return fixer.replaceText(node, unescaped);
+
+						return fixer.replaceText(
+							node,
+							quote === 'quot'
+								? unescaped.replace(/"/gu, '&quot;')
+								: unescaped.replace(/'/gu, '&apos;')
+						);
 					}
 					return fixer.replaceText(node, unescaped.replace(/</gu, '&lt;').replace(/>/gu, '&gt;'));
 				}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-config.json
new file mode 100644
index 000000000..57ebeb292
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-config.json
@@ -0,0 +1,9 @@
+{
+	"options": [
+		{
+			"checkImportedTypes": true,
+			"ignoreTypePatterns": ["BaseProps"],
+			"ignorePropertyPatterns": ["/^(_|baz)/"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-errors.yaml
new file mode 100644
index 000000000..52e74674f
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-errors.yaml
@@ -0,0 +1,12 @@
+- message: "'base' is an unused Props property."
+  line: 10
+  column: 6
+  suggestions: null
+- message: "'bar' in 'my_foo' is an unused property."
+  line: 10
+  column: 6
+  suggestions: null
+- message: "'qux' is an unused Props property."
+  line: 10
+  column: 6
+  suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-input.svelte
new file mode 100644
index 000000000..c0558eed7
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/custom-config-combination-input.svelte
@@ -0,0 +1,12 @@
+<script lang="ts">
+	import type { BaseProps, FooDTO } from './shared-types';
+	interface Props {
+		base: BaseProps;
+		my_foo: FooDTO;
+		_my_bar: string;
+		baz: string;
+		qux: string;
+	}
+	let { my_foo }: Props = $props();
+	console.log(my_foo.foo);
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-errors.yaml
new file mode 100644
index 000000000..502c15458
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-errors.yaml
@@ -0,0 +1,4 @@
+- message: "'child2' is an unused Props property."
+  line: 9
+  column: 6
+  suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-input.svelte
new file mode 100644
index 000000000..2d26bd2d9
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-external-type-input.svelte
@@ -0,0 +1,10 @@
+<script lang="ts">
+	import type { FooDTO } from './shared-types';
+
+	interface Props extends FooDTO {
+		child1: string;
+		child2: number;
+	}
+
+	let { foo, child1 }: Props = $props();
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-config.json
new file mode 100644
index 000000000..65233c1d9
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-config.json
@@ -0,0 +1,7 @@
+{
+	"options": [
+		{
+			"ignorePropertyPatterns": ["^foo$"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-errors.yaml
new file mode 100644
index 000000000..32c659188
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-errors.yaml
@@ -0,0 +1,8 @@
+- message: "'foo' is an unused Props property."
+  line: 8
+  column: 8
+  suggestions: null
+- message: "'_foo' is an unused Props property."
+  line: 8
+  column: 8
+  suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-input.svelte
new file mode 100644
index 000000000..7bee93044
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignore-property-patterns-custom-input.svelte
@@ -0,0 +1,9 @@
+<script lang="ts">
+	interface Props {
+		foo: string;
+		_foo: string;
+		bar: string;
+	}
+
+	const { bar }: Props = $props();
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-config.json
deleted file mode 100644
index c049eb81c..000000000
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-config.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-	"options": [
-		{
-			"ignorePatterns": [".*DTO$"]
-		}
-	]
-}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-config.json
new file mode 100644
index 000000000..ee109aa43
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-config.json
@@ -0,0 +1,7 @@
+{
+	"options": [
+		{
+			"ignoreTypePatterns": [".*DTO$"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-errors.yaml
similarity index 100%
rename from packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-errors.yaml
rename to packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-errors.yaml
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-input.svelte
similarity index 100%
rename from packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-pattern-partial-input.svelte
rename to packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/ignored-type-patterns-custom-input.svelte
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml
index 2f341476f..278805b2d 100644
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/imported-type-check-errors.yaml
@@ -1,6 +1,4 @@
 - message: "'name' is an unused Props property."
   line: 6
   column: 6
-  endLine: 6
-  endColumn: 20
   suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts
index a60e61ef1..e33a3a24e 100644
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/shared-types.ts
@@ -1,3 +1,14 @@
 export interface BaseProps {
 	name: string;
 }
+
+export interface FooDTO {
+	foo: string;
+	bar: number;
+	baz: BazDTO;
+}
+
+interface BazDTO {
+	qux: string;
+	quux: number;
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/bindable-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/bindable-input.svelte
new file mode 100644
index 000000000..ef2c5e990
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/bindable-input.svelte
@@ -0,0 +1,9 @@
+<script lang="ts">
+	interface Props {
+		selected: { value: string };
+	}
+
+	let { selected = $bindable() }: Props = $props();
+</script>
+
+<input type="text" bind:value={selected.value} />
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/custom-config-combination-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/custom-config-combination-config.json
new file mode 100644
index 000000000..57ebeb292
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/custom-config-combination-config.json
@@ -0,0 +1,9 @@
+{
+	"options": [
+		{
+			"checkImportedTypes": true,
+			"ignoreTypePatterns": ["BaseProps"],
+			"ignorePropertyPatterns": ["/^(_|baz)/"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/custom-config-combination-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/custom-config-combination-input.svelte
new file mode 100644
index 000000000..c34bc850e
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/custom-config-combination-input.svelte
@@ -0,0 +1,11 @@
+<script lang="ts">
+	import type { BaseProps, FooDTO } from './shared-types';
+	interface Props {
+		base: BaseProps;
+		my_foo: FooDTO;
+		_my_bar: string;
+		baz: string;
+	}
+	let { base, my_foo }: Props = $props();
+	console.log(base.age, my_foo.foo, my_foo.bar);
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/default-value-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/default-value-input.svelte
new file mode 100644
index 000000000..48d6887f4
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/default-value-input.svelte
@@ -0,0 +1,14 @@
+<script lang="ts">
+	interface Props {
+		newTaskAttributes: { attribute: number; attribute2: string };
+	}
+
+	const { newTaskAttributes = { attribute: 0, attribute2: '' } }: Props = $props();
+</script>
+
+<div class="col-span-full">
+	<div>
+		{newTaskAttributes.attribute}
+		{newTaskAttributes.attribute2}
+	</div>
+</div>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-external-type-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-external-type-input.svelte
new file mode 100644
index 000000000..920dece77
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-external-type-input.svelte
@@ -0,0 +1,10 @@
+<script lang="ts">
+	import type { FooDTO } from './shared-types';
+
+	interface Props extends FooDTO {
+		child1: string;
+		child2: number;
+	}
+
+	let { foo, child1, child2 }: Props = $props();
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-custom-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-custom-config.json
new file mode 100644
index 000000000..c22dc1654
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-custom-config.json
@@ -0,0 +1,7 @@
+{
+	"options": [
+		{
+			"ignorePropertyPatterns": ["/^[#$@_~]/"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-custom-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-custom-input.svelte
new file mode 100644
index 000000000..1dc0ca14d
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-custom-input.svelte
@@ -0,0 +1,13 @@
+<script lang="ts">
+	interface Props {
+		_internal: string;
+		$store: boolean;
+		'@decorator': string;
+		'#private': number;
+		'~tilde': boolean;
+		normalUsed: string;
+	}
+
+	const { normalUsed }: Props = $props();
+	console.log(normalUsed);
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-default-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-default-input.svelte
new file mode 100644
index 000000000..5694cb2d7
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignore-property-patterns-default-input.svelte
@@ -0,0 +1,8 @@
+<script lang="ts">
+	interface Props {
+		foo: string;
+		bar: string;
+	}
+
+	const { foo, bar }: Props = $props();
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-conditional-type-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-conditional-type-config.json
deleted file mode 100644
index 73df77c94..000000000
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-conditional-type-config.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-	"options": [
-		{
-			"ignorePatterns": ["^Conditional"]
-		}
-	]
-}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom-config.json
new file mode 100644
index 000000000..3a5c1de84
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom-config.json
@@ -0,0 +1,7 @@
+{
+	"options": [
+		{
+			"ignoreTypePatterns": ["/^Conditional/"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-conditional-type-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom-input.svelte
similarity index 100%
rename from packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-conditional-type-input.svelte
rename to packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom-input.svelte
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom2-config.json b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom2-config.json
new file mode 100644
index 000000000..347ef2b85
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom2-config.json
@@ -0,0 +1,7 @@
+{
+	"options": [
+		{
+			"ignoreTypePatterns": ["/^Internal/"]
+		}
+	]
+}
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom2-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom2-input.svelte
new file mode 100644
index 000000000..0f465ea7d
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ignored-type-patterns-custom2-input.svelte
@@ -0,0 +1,12 @@
+<script lang="ts">
+	interface InternalConfig {
+		secretKey: string;
+		debugMode: boolean;
+	}
+	interface Props {
+		config: InternalConfig;
+		value: number;
+	}
+	let { config, value }: Props = $props();
+	console.log(value, config.secretKey);
+</script>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props2-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props2-input.svelte
new file mode 100644
index 000000000..3fb8790fd
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props2-input.svelte
@@ -0,0 +1,14 @@
+<script lang="ts">
+	import GenericPopout from './GenericPopout.svelte';
+
+	let {
+		position
+	}: {
+		position: {
+			x: number;
+			y: number;
+		};
+	} = $props();
+</script>
+
+<GenericPopout {position}>Test</GenericPopout>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props3-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props3-input.svelte
new file mode 100644
index 000000000..7090054f8
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props3-input.svelte
@@ -0,0 +1,16 @@
+<script lang="ts">
+	import GenericPopout from './GenericPopout.svelte';
+
+	let {
+		wrapper
+	}: {
+		wrapper: {
+			position: {
+				x: number;
+				y: number;
+			};
+		};
+	} = $props();
+</script>
+
+<GenericPopout position={wrapper.position}>Test</GenericPopout>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props4-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props4-input.svelte
new file mode 100644
index 000000000..15bdb1277
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props4-input.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+	import GenericPopout from './GenericPopout.svelte';
+
+	let {
+		wrapper
+	}: {
+		wrapper: {
+			position: {
+				x: number;
+				y: number;
+			};
+		};
+	} = $props();
+</script>
+
+<GenericPopout x={wrapper.position.x}>Test</GenericPopout>
+<GenericPopout position={wrapper.position}>Test</GenericPopout>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts
index a60e61ef1..76d6b33c5 100644
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/shared-types.ts
@@ -1,3 +1,15 @@
 export interface BaseProps {
 	name: string;
+	age: number;
+}
+
+export interface FooDTO {
+	foo: string;
+	bar: number;
+	baz: BazDTO;
+}
+
+interface BazDTO {
+	qux: string;
+	quux: number;
 }
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ts-basic-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ts-basic-input.svelte
new file mode 100644
index 000000000..d2c509f6a
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/ts-basic-input.svelte
@@ -0,0 +1,15 @@
+<script lang="ts">
+	// fix: https://github.com/sveltejs/eslint-plugin-svelte/issues/1028#issuecomment-2728101827
+	type Prop = {
+		value: string;
+		value2: string;
+	};
+
+	interface Props {
+		myObjectProp: Prop;
+	}
+
+	const { myObjectProp }: Props = $props();
+</script>
+
+<p>{myObjectProp.value} {myObjectProp.value2}</p>
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-errors.yaml
new file mode 100644
index 000000000..ee6ce5e3e
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-errors.yaml
@@ -0,0 +1,16 @@
+- message: Unexpected mustache interpolation with a string literal value.
+  line: 2
+  column: 17
+  suggestions: null
+- message: Unexpected mustache interpolation with a string literal value.
+  line: 4
+  column: 17
+  suggestions: null
+- message: Unexpected mustache interpolation with a string literal value.
+  line: 6
+  column: 17
+  suggestions: null
+- message: Unexpected mustache interpolation with a string literal value.
+  line: 8
+  column: 17
+  suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-input.svelte
new file mode 100644
index 000000000..43dbb27d9
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-input.svelte
@@ -0,0 +1,8 @@
+<!--prettier-ignore-->
+<div data-text="{'\'"'}" />
+<!--prettier-ignore-->
+<div data-text="{"'\""}" />
+<!--prettier-ignore-->
+<div data-text='{'\'"'}' />
+<!--prettier-ignore-->
+<div data-text='{"'\""}' />
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-output.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-output.svelte
new file mode 100644
index 000000000..fd9b14743
--- /dev/null
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-useless-mustaches/invalid/quote-test02-output.svelte
@@ -0,0 +1,8 @@
+<!--prettier-ignore-->
+<div data-text="'&quot;" />
+<!--prettier-ignore-->
+<div data-text="'&quot;" />
+<!--prettier-ignore-->
+<div data-text='&apos;"' />
+<!--prettier-ignore-->
+<div data-text='&apos;"' />