diff --git a/packages/pyright-internal/src/analyzer/dataClasses.ts b/packages/pyright-internal/src/analyzer/dataClasses.ts index 0ed2710d61a4..01c4ba647b17 100644 --- a/packages/pyright-internal/src/analyzer/dataClasses.ts +++ b/packages/pyright-internal/src/analyzer/dataClasses.ts @@ -49,6 +49,7 @@ import { isFunction, isInstantiableClass, isOverloadedFunction, + isTypeSame, NoneType, OverloadedFunctionType, TupleTypeArgument, @@ -516,17 +517,20 @@ export function synthesizeDataClassMethods( if (entry.converter) { const fieldType = effectiveType; effectiveType = getConverterInputType(evaluator, entry.converter, effectiveType, entry.name); - symbolTable.set( - entry.name, - getDescriptorForConverterField( - evaluator, - node, - entry.converter, + + if (!isTypeSame(fieldType, effectiveType)) { + symbolTable.set( entry.name, - fieldType, - effectiveType - ) - ); + getDescriptorForConverterField( + evaluator, + node, + entry.converter, + entry.name, + fieldType, + effectiveType + ) + ); + } } const effectiveName = entry.alias || entry.name; diff --git a/packages/pyright-internal/src/tests/samples/dataclassConverter2.py b/packages/pyright-internal/src/tests/samples/dataclassConverter2.py index 66a68c08300f..59e94e6ebfda 100644 --- a/packages/pyright-internal/src/tests/samples/dataclassConverter2.py +++ b/packages/pyright-internal/src/tests/samples/dataclassConverter2.py @@ -4,18 +4,24 @@ from dataclasses import dataclass, field -def converter_simple(s: str) -> int: - return int(s) - +def converter_simple(s: str) -> int: ... +def converter_passThru(x: str | int) -> str | int: ... @dataclass class Foo: # This should generate an error because "converter" is not an official property yet. - field0: int = field(converter=converter_simple) + asymmetric: int = field(converter=converter_simple) + # This should generate an error because "converter" is not an official property yet. + symmetric: str | int = field(converter=converter_passThru) -foo = Foo("1") -reveal_type(foo.field0, expected_text="int") -foo.field0 = "2" +foo = Foo("1", 1) +reveal_type(foo.asymmetric, expected_text="int") +foo.asymmetric = "2" +reveal_type(foo.asymmetric, expected_text="int") # Asymmetric -- type narrowing should not occur # This should generate an error because only strs can be assigned to field0. -foo.field0 = 2 +foo.asymmetric = 2 + +reveal_type(foo.symmetric, expected_text="str | int") +foo.symmetric = "1" +reveal_type(foo.symmetric, expected_text="Literal['1']") # Symmetric -- type narrowing should occur diff --git a/packages/pyright-internal/src/tests/typeEvaluator4.test.ts b/packages/pyright-internal/src/tests/typeEvaluator4.test.ts index ce281c7bbb0b..b439e2cb2a8e 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator4.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator4.test.ts @@ -682,7 +682,7 @@ test('DataClassConverter1', () => { test('DataClassConverter2', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['dataclassConverter2.py']); - TestUtils.validateResults(analysisResults, 2); + TestUtils.validateResults(analysisResults, 3); }); test('DataClassPostInit1', () => {