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

[✨Feature Request]: add support aliases #163

Open
PandaWorker opened this issue Sep 16, 2023 · 9 comments
Open

[✨Feature Request]: add support aliases #163

PandaWorker opened this issue Sep 16, 2023 · 9 comments
Assignees
Labels
enhancement New feature or request

Comments

@PandaWorker
Copy link

How about adding such functionality?

import * as v from 'valibot';

const schema = v.object({
  name: v.alias('first_name', v.string())
});

const user = v.parse(schema, {
  first_name: 'anonym'
});

console.log(user.name) // anonym
import * as v from 'valibot';

const schema = v.object({
  name: v.alias('user.name', v.string())
});

const user = v.parse(schema, {
 user: {
   name: 'anonym'
 }
});

console.log(user.name) // anonym
import * as v from 'valibot';

const schema = v.object({
  name: v.alias('user[0]', v.string())
});

const user = v.parse(schema, {
 user: ['anonym', 'lastname']
});

console.log(user.name) // anonym
@fabian-hiller
Copy link
Owner

Thank you for sharing this idea. At the moment I am not sure if we should implement this. Is there a schema library that supports this feature? alias seems to be quite powerful, which will make it difficult to implement. Also, I am unsure how alias will interact with the other schema functions. I welcome feedback on this from others.

@fabian-hiller fabian-hiller self-assigned this Sep 16, 2023
@fabian-hiller fabian-hiller added the enhancement New feature or request label Sep 16, 2023
@fabian-hiller
Copy link
Owner

I am closing this issue due to inactivity. I welcome feedback if there is still interest in this feature.

@kingbri1
Copy link

Hi Fabian. I want to contribute back to this issue since aliases are features of validation libraries in other languages. However, I haven't seen this behavior used in TS validation libs which was pretty surprising.

Examples:
Python - Pydantic
Rust - Serde

Here's an example of a Pydantic model with aliases:

class TestModel(BaseModel):
    static_field: Optional[float] = 0.0

    aliased_field: Optional[float] = Field(
        default=0.0,
        alias=AliasChoices("aliased_field", "dynamic_field")
    )

And from here, if dynamic_field is passed, it gets mapped to aliased_field and can be referenced in further code as such.

@fabian-hiller
Copy link
Owner

It is possible to implement it as a transformation action. Here is an example API:

import * as v from './dist/index.js';

const Schema = v.pipe(
  v.object({
    email: v.pipe(v.string(), v.email()),
    name: v.pipe(v.string(), v.nonEmpty()),
  }),
  v.aliasKey('name', 'first_name')
);

// Now input will be: { email: string, name: string }
// And output will be: { email: string, first_name: string }

Issue #981 is partly related.

@kingbri1
Copy link

Sorry, that's a bit hard to understand from my end. So, aliasKey is the custom transformation action? Do you mind pointing me to resources on how that can be created?

@fabian-hiller
Copy link
Owner

Yes, aliasKey would be the custom action. The name was just an initial idea.

Here is some context:

  • We can't add the action to the key itself, because the transformation takes place in the outer object
  • That's why the actions need to be placed in the pipeline of the object schema
  • The action must transform not only the output data but also the output type
    • Something like Omit<TObjectOutput, TOldKey> & { [TKey in TNewKey]: TObjectOutput[TOldKey] } may work
  • Parsing from snake_case to camelCase #981 is partly related – feel free to have a look
  • I would probably copy and modify the source code of transform when implementing the action

@kingbri1
Copy link

Thanks for the context. I'll take a look at it, but I don't believe I'm skilled enough in TS to properly PR this action. Can you consider reopening the issue and maybe someone else will take it up before I can?

@fabian-hiller
Copy link
Owner

fabian-hiller commented Dec 29, 2024

Yes, don't worry. We could look into this when working on #981.

@fabian-hiller fabian-hiller reopened this Dec 29, 2024
@michachen
Copy link

michachen commented Dec 29, 2024

import * as v from 'valibot';

const schema = v.object({
  name: v.alias('user.name', v.string())
});

const user = v.parse(schema, {
 user: {
   name: 'anonym'
 }
});
console.log(user.name) // anonym

@fabian-hiller @PandaWorker
The user.name alias string is like lodash/get
This is actually exactly what im looking for. Imagine you recieve a JSON from your server but the backend team wrote naming or even data nesting in a quirky way. It would be nice to actually provide the original object and alias nested props from it. It will allow you to rearange your output object the way you feel like without making changes or rearranging namings/nesting on the backend side. And the the infered type would be also the way you like so its awesome IMO.

It would be possible to actually write the alias action if there was some way to pass the original object or some custom object via parse/safeParse config or global config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants