Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types): add properties-of<T> type #7359

Merged
merged 9 commits into from Feb 28, 2022
1 change: 1 addition & 0 deletions docs/annotating_code/type_syntax/atomic_types.md
Expand Up @@ -52,6 +52,7 @@ Atomic types are the basic building block of all type information used in Psalm.
- `key-of<Foo\Bar::ARRAY_CONST>`
- `value-of<Foo\Bar::ARRAY_CONST>`
- `T[K]`
- [`properties-of<T>`](utility_types.md#properties-oft)

## Top types, bottom types

Expand Down
40 changes: 40 additions & 0 deletions docs/annotating_code/type_syntax/utility_types.md
@@ -0,0 +1,40 @@
# Utility types
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are key-of and value-of documented? Maybe they should be added here? Maybe SomeClass::CONST_* as well? Probably others?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add these as well in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added key-of and value-of, SomeClass::CONST_* also could need some documentation, but I think it's not a utility type if you look at typescripts definition (https://www.typescriptlang.org/docs/handbook/utility-types.html)


Psalm supports some _magical_ utility types that brings superpower to the PHP type system.

## `properties-of<T>`

This collection of _utility types_ construct a keyed-array, with the names of non-static properties of a class as keys,
and their respective types as values. This can be useful if you need to convert objects into arrays.

```php
class A {
public string $foo;
public int $bar;

/**
* @return properties-of<self>
*/
public function asArray(): array {
return [
'foo' => $this->foo,
'bar' => $this->bar,
];
}

/**
* @return list<key-of<properties-of<self>>>
*/
public function attributeNames(): array {
return ['foo', 'bar']
}
}
```

### Variants

Note that `properties-of<T>` will return **all non-static** properties. There are the following subtypes to pick only
properties with a certain visibility:
- `public-properties-of<T>`
- `protected-properties-of<T>`
- `private-properties-of<T>`