Skip to content

Brainstorming: Pick types #1125

Open
Open
@Tinche

Description

@Tinche

This is something for us to consider, and it's come up on the typing mailing list a few times.

A Pick type is a TypeScript thing. You take an existing type, and you create a new type from a subset of that type's fields. Essentially, you pick attributes from the original type.

Example from the TS docs:

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
 
type TodoPreview = Pick<Todo, "title" | "completed">;

This might be useful in a bunch of contexts, like:

  • REST APIs - imagine a POST or PUT request, but it shouldn't have an ID in the model since the ID is in the URL, or autogenerated by server. You'd pick the fields you need
  • Database stuff - loading projections, so you get only the fields you need

Why the additional complexity instead of just defining what you need from scratch? DRY I guess, and keeping the origin and pick models in sync automatically.

I think in runtime we can do this relatively easily. Typing-wise though it'll require a Mypy plugin change for sure.

If we do want to do this, what would the API look like?

@define
class Todo:
    title: str
    description: str
    completed: bool

from attrs import pick, fields as f

TodoPreview = pick(Todo, f(Todo).title, f(Todo).description)

# Alternatively
TodoPreview = pick(Todo, "title", "description")

# Alternatively. This syntax feels extensible.
TodoPreview = pick(Todo, title=True, description=True)

The last syntax feels like it could be extended into the Omit type (the opposite of pick - where you exclude types).

TodoPreview = pick(Todo, completed=False)

I think at runtime we'd just create a new type, inherinting from object, while copying over the attributes and their defaults. So TodoPreview is not a subclass or Todo, or vice versa. There should be some sort of link back to the origin class at runtime via a hidden attribute, but that's about it.

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    ThinkingNeeds more braining.TypingTyping/stub/Mypy/PyRight related bugs.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions