A
arktype3mo ago
PIat

Conform to an existing type

Hello! Is there a way to force a def to conform to an existing typescript type?
export const chatDef = type({
id: 'number',
chatType: "private' | 'public'",
title: 'string',
username: 'string'
// force this
}) satisfies Pick<Jsonify<Chat>, 'id' | 'chatType' | 'title' | 'username'>
export const chatDef = type({
id: 'number',
chatType: "private' | 'public'",
title: 'string',
username: 'string'
// force this
}) satisfies Pick<Jsonify<Chat>, 'id' | 'chatType' | 'title' | 'username'>
18 Replies
ssalbdivad
ssalbdivad3mo ago
declare<Expected>().type({
a: "string",
"b?": "number"
})
declare<Expected>().type({
a: "string",
"b?": "number"
})
Full tests: https://github.com/arktypeio/arktype/blob/098409b41fb5c478f6ca455a48cad92454db7e63/ark/type/__tests__/declared.test.ts
PIat
PIatOP3mo ago
Amazing! 😍 Thank you
ssalbdivad
ssalbdivad3mo ago
Could get messy if there are subtypes like <5 or morphs but for simple TS types it should be straightforward
PIat
PIatOP3mo ago
Yes, I only have simple unions
ssalbdivad
ssalbdivad3mo ago
It would still work, but it checks for bidirectional equality so you'd need to import those subtypes from arktype
PIat
PIatOP3mo ago
Why would subtypes mess with it? Will <5 not turn to number?
ssalbdivad
ssalbdivad3mo ago
Only when it's inferred out, the internal type representation is number.lessThan<5> which is branded Having the extra type metadata encoded in the type means people can opt in to brands in the future but also we can do stuff like pattern matching where you need to know if a type has constraints on it to know if the case has been covered
PIat
PIatOP3mo ago
It's sooo cool to literally just copy unions over 🤩 It's so comfortable to declare types with Arktype and makes everything so simple and concise I see! Thank you
ssalbdivad
ssalbdivad3mo ago
I'm glad it's helpful, that feature is pretty unique since it's notoriously difficult to say "I want a Zod object with this type." And getting autocomplete for the keys is cool
PIat
PIatOP3mo ago
Urgh, Zod...
ssalbdivad
ssalbdivad3mo ago
I do need to figure out how I want to expose the subtype/morph types though Ehh, a problem for another day. Hopefully most people reimplementing existing type definitions just need the pure shapes
PIat
PIatOP3mo ago
Or doing things like this 🤩
function addJob<
J extends JobName,
Input extends Jobs[J]['input']['inferIn'],
Output extends Jobs[J]['output']['inferOut'],
>() {}
function addJob<
J extends JobName,
Input extends Jobs[J]['input']['inferIn'],
Output extends Jobs[J]['output']['inferOut'],
>() {}
And then having the types checked all across the function and having inputs and outputs asserted and everything with a line of code ahhhh 🤩 With a single source of truth
ssalbdivad
ssalbdivad3mo ago
I'm glad that's working out so well for you, definitely can be nice for piping like that. Being able to deeply extract one side of a morph with .in and .out I think also has a lot of potential in some situations
PIat
PIatOP3mo ago
Are there test examples?
ssalbdivad
ssalbdivad3mo ago
(at runtime, it's a lot easier in terms of just the types haha) These tests are in @ark/schema but the same thing exists in arktype: https://github.com/arktypeio/arktype/blob/cda83764df50431b0f5f8c8ba02c1de87bfb1010/ark/schema/__tests__/morphs.test.ts You just define a type and if it has morphs at the root or any nested path, it will extract them out
PIat
PIatOP3mo ago
I see it's returning the same type object? I guess it's needed for complex scenarios?
ssalbdivad
ssalbdivad3mo ago
Here's a simpler example with ArkType syntax:
const t = type({
foo: type("number").pipe(n => `${n}`, type.string)
})

attest<{ foo: number }>(t.in.t)
attest(t.in.expression).snap("{ foo: number }")

attest<{ foo: string }>(t.out.t)
attest(t.out.expression).snap("{ foo: string }")
const t = type({
foo: type("number").pipe(n => `${n}`, type.string)
})

attest<{ foo: number }>(t.in.t)
attest(t.in.expression).snap("{ foo: number }")

attest<{ foo: string }>(t.out.t)
attest(t.out.expression).snap("{ foo: string }")
I think it could be useful even for simpler scenarios if you have morphs in an object but want one side or the other
PIat
PIatOP3mo ago
Ooooh I think I get it now Will have this in the back of my mind for the future, thank you 😊
Want results from more Discord servers?
Add your server