Overridden properties in subclasses can change the type of the property #336

Open
opened 2025-12-30 01:23:38 +01:00 by adam · 1 comment
Owner

Originally created by @sin-ack on GitHub (Aug 8, 2025).

Reproduced with Pkl 0.29.0.

Reproducer:

open class Foo {
    foo: Int
}

class Bar extends Foo {
    foo = "foo"
}

output {
    value = new Bar {}
}

This is more of a clarification question: Should this be allowed? As a follow-up, what should one do if they don't want this to be allowed in their schema? My use-case is the following:

open class BaseThing {
    // This will be exposed on the final JSON/YAML/etc. output so that code consuming this value can know what type it's dealing with.
    fixed type: String
}

class DerivedThing extends BaseThing {
    fixed type = 123 // Allowed right now
}

Right now derived classes can set type to anything, which causes chaos.

Follow-up to the follow-up: In case of property overrides in subclasses, should aspects of the property like documentation and field type be preserved? Right now, if one specifies the type on the superclass and reflects the subclass, the type of the overridden field will be UnknownType unless explicitly specified (which causes code generator sadness).

Originally created by @sin-ack on GitHub (Aug 8, 2025). Reproduced with Pkl 0.29.0. Reproducer: ```pkl open class Foo { foo: Int } class Bar extends Foo { foo = "foo" } output { value = new Bar {} } ``` This is more of a clarification question: Should this be allowed? As a follow-up, what should one do if they don't want this to be allowed in their schema? My use-case is the following: ```pkl open class BaseThing { // This will be exposed on the final JSON/YAML/etc. output so that code consuming this value can know what type it's dealing with. fixed type: String } class DerivedThing extends BaseThing { fixed type = 123 // Allowed right now } ``` Right now derived classes can set `type` to anything, which causes chaos. Follow-up to the follow-up: In case of property overrides in subclasses, should aspects of the property like documentation and field type be preserved? Right now, if one specifies the type on the superclass and reflects the subclass, the type of the overridden field will be `UnknownType` unless explicitly specified (which causes code generator sadness).
Author
Owner

@bioball commented on GitHub (Aug 8, 2025):

At the moment, Pkl will allow you to override the type of a property with no restrictions.

This is something that we'd like to change in the future, but it needs some thinking through.
From a type perspective, it's only sound to override the type of a property if:

  1. The overridden type is a subtype of the parent type
  2. The property is fixed or const (only output properties should be overridable)

Sidenote: possibly we should only enforce rule 1, but not 2. This is a more pragmatic approach for Pkl.

However, right now, Pkl doesn't understand what a subtype is. We have some initial ideas for how to implement this, but nothing concrete right now.

By the way, both snippets that you've posted are errors. Because the child property doesn't declare a type, the property's type is not actually overridden. They both result in this error:

–– Pkl Error ––
Expected value of type `Int`, but got type `String`.
Value: "foo"

2 | fixed foo: Int
               ^^^
@bioball commented on GitHub (Aug 8, 2025): At the moment, Pkl will allow you to override the type of a property with no restrictions. This is something that we'd like to change in the future, but it needs some thinking through. From a type perspective, it's only sound to override the type of a property if: 1. The overridden type is a subtype of the parent type 2. The property is `fixed` or `const` (only output properties should be overridable) _Sidenote: possibly we should only enforce rule 1, but not 2. This is a more pragmatic approach for Pkl._ However, right now, Pkl doesn't understand what a subtype is. We have some initial ideas for how to implement this, but nothing concrete right now. By the way, both snippets that you've posted are errors. Because the child property doesn't declare a type, the property's type is not actually overridden. They both result in this error: ``` –– Pkl Error –– Expected value of type `Int`, but got type `String`. Value: "foo" 2 | fixed foo: Int ^^^ ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/pkl#336