-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
refactor(data-types): convert data-types to TS #13799
Conversation
@allawesome497 checkout #12941 which was updated this week |
Oh I completely missed that. My change covers a few things that aren't handled in that pr such as named exports, inline static keys (e.g. |
I think my TS skills don't really suffice to review this beast. I have an opinion the wording however: "Acceptable" type (ie what it'll accept as user input, e.g. for dates this is numbers, Dates, or strings) "Sane" type - What sequelize will normally return (e.g. for dates, Date) "Raw" type - Whatever we need to deserealize for a type. (e.g. for a boolean this is a number, buffer, or string) |
Adding @ephys as well :) |
@allawesome497 2 questions in general...
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, this is my only note
lib/utils/class-to-invokable.ts
Outdated
return new Class(...args); | ||
}, | ||
export function classToInvokable< | ||
Class extends new (...args: Array<never>) => any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it normal that args is Array<never>
? Shouldn't it be Array<any>
or Array<unknown>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also be Array<any>
(and that's what I'd normally put). I just did this since eslint recommended it and I was unsure if it'd work. Will probably change it back to Array<any>
since that's more intuitive IMO.
Sounds good, though I think that
|
How are we doing on this front? I just wanted to point out one more time, that we are now targeting v7 and could hence drop support for any weird hack that was introduced earlier. |
Have been pretty busy recently, back on it for now. Looks like we'll need to re-model how |
I'm researching how we could support customising what type Sequelize must output for a given DataType. I'm waiting on this PR to be merged before properly experimenting but since you've knee-deep in DataTypes I'd like to know if my current draft would impact your decisions in this PR, like for Also I'd still like to bikeshed the names of the 3 types based on how I understood them:
|
Nope, I think your current draft is fine - though it will be a pain to migrate typing to this. As I'm finding, there's a lot of undocumented dialect-specific logic around typing :/. As for renaming: I will do this, I just haven't yet since there hasn't been a clear choice in terms of names yet (and I don't see this PR getting merged soon, given its scale so I figure its worth waiting). |
Yup! Not looking forward to it but I want the feature enough to be motivated at least |
🤔 I thought I responded to this but I don't see any response.
I've opted to convert everything to TS first and add tests later (however: this will be before this PR is merged). I added some more details to the PR description.
Yep! That should be done by the time I merge this if I haven't already removed the file. |
converts data-types to TS
6de690b
to
210279c
Compare
}; | ||
} | ||
|
||
this.options = options; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be a good opportunity to normalize options
. We should either have options
, or _length
& co. But not both, otherwise we need to keep both in sync and it's error prone.
constructor(precision: number, scale?: number); | ||
constructor(...args: DecimalConstructorParams); | ||
constructor(precision?: number | DecimalOptions, scale?: number) { | ||
if (typeof precision === 'object') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use isObject
from lodash instead
} | ||
|
||
this._precision = this.options.precision; | ||
this._scale = this.options.scale; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment about deduplicating options
& instance fields
public validate(value: AcceptedNumber): asserts value is AcceptedNumber; | ||
public validate(value: AcceptedNumber): true { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't this be simplified to:
public validate(value: AcceptedNumber): asserts value is AcceptedNumber; | |
public validate(value: AcceptedNumber): true { | |
public validate(value: AcceptedNumber): asserts value is AcceptedNumber { |
return 'DECIMAL'; | ||
} | ||
|
||
public validate(value: AcceptedNumber): asserts value is AcceptedNumber; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AcceptedNumber
doesn't include string. But DECIMAL
should accept strings to avoid loss of precision
RawType = AcceptedType, | ||
> { | ||
public static readonly key: string = 'ABSTRACT'; | ||
// @internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't stripInternal
only apply to jsdoc? (either way this should be jsdoc)
? Instance | ||
: T; | ||
|
||
export type AcceptableTypeOf<T extends DataType> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the purpose of these different types should be documented
|
||
// If T is a constructor, returns the type of what `new T()` would return- | ||
// otherwise, returns T | ||
export type Constructed<T> = T extends abstract new () => infer Instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this the same as the built-in type InstanceType
?
import { logger } from '../../utils/logger'; | ||
import { validator as Validator } from '../../utils/validator-extras'; | ||
|
||
const warnings: Record<string, boolean> = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const warnings: Record<string, boolean> = {}; | |
const warnings: Record<string, boolean> = Object.create(null); |
@@ -0,0 +1,9 @@ | |||
export * from './dialects/abstract/data-types'; | |||
export * as db2 from './dialects/db2/data-types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the reason for exposing these? Shouldn't users only use DataTypes.x
and not DataTypes.postgres.x
?
Some comments may be unrelated to this PR.
As long as they're well documented, I'm fine with it |
}; | ||
|
||
Reflect.defineProperty(this, 'types', prop); | ||
Reflect.defineProperty(this.prototype, 'types', prop); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to add it to the prototype too?
return null; | ||
} | ||
|
||
static readonly parse = this.prototype._sanitize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to have the _sanitize
instance method call the static parse
method instead of getting something from the prototype
|
||
public toSql() { | ||
if (this._precision || this._scale) { | ||
return `DECIMAL(${[this._precision, this._scale] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if scale is specified but precision is not, we should throw with a clear error message
case 'tiny': | ||
return 'TINY_TEXT'; | ||
case 'medium': | ||
return 'MEDIUM_TEXT'; | ||
case 'long': | ||
return 'LONG_TEXT'; | ||
default: | ||
return this.key; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why were these changed, they should be TINYTEXT
& co
); | ||
} | ||
|
||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove these return true
from validate.
Closing in favor of #14505. |
Pull Request Checklist
Please make sure to review and check all of these items:
npm run test
ornpm run test-DIALECT
pass with this change (including linting)?Description Of Change
converts data-types to TS.
I've typed this in a way that the types of columns can be extracted from
sequelize.define
(in theroy - haven't gotten far enough to test that yet). I also added some generic types to assist in getting types of a DataType.For any reviewers, I've labled 3 (ts) types which are relevant to each DataType:
Child PRs
The approach of this PR
Due to the size of this change, I've opted to split up this PR into many to make it more reviewable.
Here's the steps I'll be taking: